• No results found

JavaScript in SVG

In document Using SVG With CSS3 and HTML5 (Page 56-60)

If you’ve used JavaScript to create a dynamic HTML page, you can use it to create dynamic SVG. SVG elements inherit all the core DOM methods to get and set attributes and styles.

Of course, there are a few complications: SVG is a namespaced XML language, so you’ll need to use the namespace-sensitive DOM meth‐

ods when creating elements or setting xlink attributes. Also be aware that some methods you may be familiar with from HTML are not part of the core DOM specifications, such as the .innerHTML() method to parse a string of markup or the .focus() method to con‐

trol keyboard focus. (Focus and blur control have been added to SVG 2, but aren’t universally implemented yet.) Even worse, some features such as .className look similar but are structured differ‐

ently.

As a sort of consolation prize for the missing HTML DOM meth‐

ods, the SVG specifications introduced a variety of SVG-specific methods and properties to make graphical calculations easier.

Unfortunately, many of these features were not universally imple‐

mented, and some have become obsolete as SVG switches to an ani‐

mation model more compatible with CSS. Nonetheless, there are still a few useful features that can be relied on in most web browsers.

To include a script within a stand-alone SVG file, you can include a

<script> element anywhere between the opening and closing <svg>

tags. To include an external JavaScript file, use an xlink:href attribute (not src like in HTML) to give the file location. If you instead include the script in between the <script> tags, remember to wrap it in an XML character data block, so that less-than and greater-than operators do not cause XML validation errors.

You can specify the scripting language using the type attribute on individual <script> elements, or the contentScriptType attribute on the

<svg> element. However, it really isn’t necessary;

the default type, application/ecmascript (standard JavaScript) is the only type currently supported in most web browsers.

Most browsers—though not necessarily other tools—will also recognize the types application/javascript and text/

javascript as synonyms. But avoid confusion by relying on the default.

We’ve already alluded to one common use of scripted SVG: cross-browser animation support. Example 2-1 shows JavaScript that could be used to replace the CSS animation from Example 1-6 or Example 1-7 from Chapter 1. The code uses classes to select the ele‐

JavaScript in SVG | 55

ments, so works with either the simple or labelled SVG markup: just remember to remove the CSS animation code from the <style> ele‐

ment! The JavaScript should be inclued at the end of the file (right before the closing </svg> tag), inside a <script><![CDATA[ /*

script goes here */ ]]></script> block.

Example 2-1. Using JavaScript to animate an SVG stoplight

(function(){

var lights = ["green", "yellow", "red"];

var nLights = lights.length;

var lit = 2;

function cycle() { lit = (lit + 1) % nLights;

var litElement, selector;

for (var i=0; i < nLights; i++ ) { selector = "." + lights[i] + " .lit";

litElement = document.querySelector(selector);

litElement.style.setProperty("visibility", (i==lit)? "visible" : "hidden",

null);

} } cycle()

setInterval(cycle, 3000);

})()

The code is contained in an anonymous function, which creates a closure to encapsulate variables. Although not required, this is good coding practice to avoid conflicts between different scripts on a page.

The lights array holds the class names that distinguish each light group. Since the number of lights won’t be changing, we can store it in a variable as well.

The red light is initially lit in the markup; this corresponds to index 2 in the lights array; JavaScript array indices start at 0 for the first element.

The cycle() function will change the lights.

To start the cycle, the lit variable is advanced by one; the mod‐

ulus operator (%) ensures that it cycles back to 0 when it reaches the length of the array.

At each stage of the cycle, each color of light will be modified to either hide or show the “lit” graphic.

The “lit” <use> element for each color is retrieved using the querySelector() method; a CSS selector of the form “.red .lit”

will select the first element of class “lit” that is a child of an ele‐

ment with class “red”.

The display style property is set to either block or none accord‐

ing to whether this light should be lit. Modifying the style prop‐

erty sets an inline style, which over-rides the presentation attribute in the markup.

The cycle function is run once to turn the light green, and then is called at regular intervals on a 3-second (3000ms) timer.

The anonymous function is run immediately: the syntax (function(){ /*...*/ })() parses and runs the encapsulated code.

Although this isn’t a full web application—there is no interaction with the user—it demonstrates how SVG elements can be accessed and modified from a script.

There’s nothing SVG-specific about the JavaScript code: it selects elements using CSS selectors and the document.querySelector() method, and sets the visibility style according to which lit bulb should be displaying. A timer runs the cycle again after every three-second interval.

JavaScript in SVG | 57

The querySelector() method and its sibling querySelectorAll() are convenient ways to locate elements using a combination of tag names, class names, and relationships to other elements. However, versions of Webkit and Blink browsers prior to mid-2015 had a bug that prevented them from working for SVG mixed case tag and attribute names, such as linearGradient or viewBox in HTML docu‐

ments. To improve backwards compatibility, use classes on these elements if you need to select them in your code.

JavaScript and SVG can do more than re-create simple animations, of course. Scripts can be used to implement complex logic and user interaction. They are also useful for calculating the coordinates of shapes in geometric designs and data visualizations. You could even use JavaScript to implement your own form-input elements or wrapped-text blocks in SVG. But it’s generally easier to use HTML for that.

The stoplight graphic now cycles through green, yellow, and red lights when you view it in any modern web browser, and even in Internet Explorer 9 (the earliest IE to have SVG support). However, you won’t get any animation, in any browser, if you reference the SVG from the src attribute of an HTML <img> element!

It’s an extra complication when dealing with SVG in web pages: the behavior of SVG on the web can be quite different, depending on how the SVG is incorporated in the page.

In document Using SVG With CSS3 and HTML5 (Page 56-60)