Wednesday, July 1, 2015

The Basics of jQuery SVG

I know I've been writing more about SVG lately. This is because I am working on a new design for caseyleonard.com that is basically all SVG embedded in an HTML page. But static content is boring! I want a website that moves or something!

One way I can accomplish this is with jQuery SVG, a jQuery plugin that lets you interact with SVGs via JavaScript. I tried to do some basic things with it, just to see if I would like it.

First of all, I will report that the online documentation for jQuery SVG is not the greatest. I found the site navigation to be confusing and explanations of the code samples were hard to understand. There are some good demos, but it's not exactly clear why they work in all cases. I had to do a bit of experimentation in order to figure out the basics.

My goal was to have a very wide scene rendered via SVG. You can only see part of the scene at any given time because of the viewBox settings. Clicking on some elements in the SVG will cause the viewBox to scroll a new part of the scene into view.

Here is a stripped-down version of the HTML page. Most of the SVG has been removed so save space.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery SVG Test</title>
<link rel="stylesheet" type="text/css" href="css/jquery.svg.css">
<link rel="stylesheet" type="text/css" href="css/default.css">
</head>

<body>

    <div id="svgContainer">

        <svg id="svgScene" xmlns="http://www.w3.org/2000/svg"
                viewbox="0 0 500 282">
            ....
            <g id="ceo-frog">
                ....
            </g>
            <g id="science-frog">
                ....
            </g>
            ....
        </svg>

    </div>

</body>

<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="js/jquery.svg.js"></script>
<script type="text/javascript" src="js/jquery.svgdom.js"></script>
<script type="text/javascript" src="js/jquery.svganim.js"></script>

</html>

At the bottom, you can see the jQuery and jQuery SVG imports. jQuery SVG is very modularized - you need to include the base plus any of the different sub-modules you wish to use. I am using the DOM module to allow me to access the DOM of the SVG much like the DOM of the HTML. I am also using the Animations module to allow me to use jQuery animation with the SVG attributes. Also note that there is a small CSS file included as part of the jQuery SVG package that you'll want to include.

Now it gets weird. Look at the following JavaScript needed to make the viewBox move.

$(function() {

    $("#svgScene").svg();

    var svg = $("#svgScene").svg("get");

    $("#ceo-frog", svg.root()).click(function(e) {
        $("#svgScene").animate({svgViewBox: "500 0 500 282"}, 1500);
    });

    $("#science-frog", svg.root()).click(function(e) {
        $("#svgScene").animate({svgViewBox: "1000 0 500 282"}, 1500);
    });

});

Everything is wrapped in a function that gets called when the page is fully loaded. The first thing that must happen is that the SVG code must be initialized on the SVG element in the document. There on line 5, I used the standard jQuery selector to get the SVG element by id and then call .svg() on it. After that, I can get an SVG object by calling .svg("get") on that same element again.

You need the svg object in order to make calls to find elements inside the SVG. See lines 7 and 11 where I set up click listeners on two of the objects in the SVG scene (a picture of CEO Frog and a picture of Science Frog). The object returned from calling svg.root() must be passed as the second parameter to the normal jQuery selector function in order for it to work properly.

Finally, likes 8 and 12 reveal how to animate the viewBox of the SVG. Using the selector for the SVG root element and a call to the standard jQuery .animate() function, it is possible to create a smooth scroll transition between two viewBox configurations. The most important thing to realize is that you can't use the parameter "viewBox" as input to the animate function. You have to animate the "svgViewBox" attribute instead. I know, there is no actual attribute in the document named svgViewBox. It's just viewBox. But the SVG attributes have special names (mostly the same names with "svg" at the beginning but not always - see the documentation) that you must use for animation purposes. The viewBox attribute is made up of four numbers. The first two are the x and y coordinates for the top left corner of the viewBox. The next number is the width of the view and the last number is the height. In my animation, I change the first number to add 500 each time, which essentially scrolls the view sideways by its width.

I don't know about you, but I find the API for this module to be a bit odd. Yes, I got it to work, but I didn't really feel good about it.

Bottom line: I think I'm going to try Snap.svg next before I make a decision on what to use.

Amphibian.com comic for 1 July 2015