09 Mar 2011 Editor's note: Some browsers support SVG animations. These animations were tested in Microsoft Internet Explorer with the Adobe plug-in, Google Chrome, and Mozilla Firefox. The sample animations worked best in Internet Explorer with the Adobe plug-in. Part of the animations worked in Google Chrome. In Download, find the sample SVG files in x-matters42-examples.zip and HTML files that embed the sample SVG files in x-matters42-html-examplefiles.zip.
SVG has been a W3C recommendation for some time now but has been slow to catch on in the wider Web. That might be changing now that Mozilla (Firefox), Apple (Safari), and Opera all support (or are about to support) SVG in their browsers, without plug-ins. The Linux desktops Gnome and KDE also support SVG for use in themes, icons, backgrounds, and games. Until now, the main way to view SVG was to use the Adobe plug-in (see Resources), which I used to test the example code.
What exactly is SVG, and when is it appropriate to use? SVG has been compared to PDF, PostScript, Flash, and HTML, but it has elements of all without duplicating any of them. SVG is complex, which allows it to be many things to many people while remaining a text format (Google can index it) and XML (you can manipulate it with the DOM). At the most basic level, it is an XML language for describing vector graphics -- pictures made by drawing lines (as opposed to bitmap graphics -- pictures made by drawing pixels). But SVG can also contain and manipulate bitmaps, text, even sound files. In addition, it can:
- Describe ways to apply noise and other effects to vector or bitmap images
- Specify elaborate color gradients and patterns
- Provide links to other parts of the Web
- Be scripted and transformed, animated, and styled
- Be interactive in many ways.
I want to follow up on David's earlier XML Matters column on SVG by talking about SVG animation and interactivity, specifically its declarative animation and interactivity.
Note: To view the SVG documents in this article, you need an SVG viewer which you can find in Resources. You can also download a .zip file that includes all associated SVG files.
Declarative programming is more like a description of what you want to happen, without worrying about the details of how to make it happen. Common examples of declarative programming include spreadsheets, SQL, XSLT, and programming languages such as Haskell. Other programming languages that provide a mix of declarative and procedural constructs include Lisp and Python. Several XML dialects are moving to include more declarative features in place of more complex and/or repetitive JavaScript for handling tasks such as forms validation (XForms), data mining (XQuery), transformations (XSLT), event handling (XML Events), and animation (Synchronized Multimedia Integration Language, or SMIL).
SMIL (see Resources) -- a language for mixing video, pictures, music, and text in real time -- has been adopted and extended by SVG. Much of the declarative animation in SVG is borrowed directly from SMIL (without using the SMIL namespace), although some aspects of SMIL were left out because they made no sense in the context of SVG, and others were extended. SMIL is used in RealNetworks' RealPlayer, in Apple's QuickTime, and (as XHTML+SMIL) in Microsoft's Internet Explorer. SMIL is a tool for choreography of these different media formats in response to time and events.
The declarative capability that SVG inherits from SMIL lets you animate graphics (for example) either at predetermined times, or in response to certain events. You can declare five types of animation and use many events to trigger your animations.
It's time to show you some examples.
The first example creates a canvas for the rest of the examples in this article. I'm going to drift back to grade school and use sketches of rockets and UFOs, so the background will be a simple sheet of lined notebook paper with three punch holes. This example doesn't use animation. I merely set up a canvas reminiscent of a grade-school notebook, ready for doodles. The paper is quite simple, consisting of a single svg element containing a short section of definitions: a line pattern and a small circle. Then, in the body (outside the defs) I draw a rectangle over the whole page, filling it with the line pattern. Then I grab the circle I just defined and draw it in three places. Listing 1 shows the SVG code for the notebook-paper example.
Listing 1. A sheet of notebook paper
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" fill="white">
<defs>
<pattern id="single_line" x="0" y="0" width="1" height="32"
patternUnits="userSpaceOnUse" viewBox="0 0 1 32">
<line x1="0" y1="32" x2="1" y2="32"
stroke="lightblue" stroke-width="0.5"/>
</pattern>
<circle id="single_hole" width="28" height="28"
cx="14" cy="14" r="14"
fill="white" stroke="black" stroke-width="0.5"/>
</defs>
<rect x="0" y="0" width="100%" height="100%"
fill="url(#single_line)" stroke="none"/>
<use xlink:href="#single_hole" x="32" y="10%"/>
<use xlink:href="#single_hole" x="32" y="50%"/>
<use xlink:href="#single_hole" x="32" y="90%"/>
</svg>
|
To run this example in your browser, download the example code (01_paper.svg in Download). If you have installed an SVG viewer, click to see this example.
The second example adds one path element to the definitions and uses it once in the body of the svg (see Listing 2). The path is made up of a move statement (Mx y) and line-to statements (Lx y) in absolute coordinates. (Statements using relative coordinates would be lowercase.) The d attribute contains 1,072 statements (gathered through Wacom tablet), so I've trimmed it for brevity in Listing 2. You can view the full file all its glory in the example code (see 02_rocket_static.svg in Download).
Listing 2. A rocket ship (changes only)
<defs>
[...]
<path id="rocket" stroke-width="3" stroke-linejoin="round"
stroke-linecap="round" stroke="#4C4C4C" fill="white"
d="M23 8 L21 11 L21 11 L20 16 [etc...]"/>
</defs>
[...]
<use x="50%" y="50%" xlink:href="#rocket"/>
|
So far, my doodle is as static as the virtual paper it's sitting on (see Figure 1), but that will change in the next example.
Figure 1. The rocket
To run this example in your browser, download the example code. If you have installed an SVG viewer, click to see graphic.
At last it's time for some motion. The rocket will follow a circle to demonstrate some of the features you can expect from SVG: path following and auto-rotation. This third example demonstrates the first type of declarative animation I'll cover -- the animateMotion element (see Listing 3).
Listing 3. A rocket ship on the move (changes only)
<defs>
[...]
<path id="rocket2" transform="rotate(90)" [...]/>
<path id="circle" stroke-width="4" fill="none" stroke="#000000"
d="M100 350 A300,300 0 1,1 700,350 A300,300 0 1,1 100,350"/>
</defs>
[...]
<use xlink:href="#rocket">
<animateMotion rotate="auto" dur="30s" repeatCount="indefinite">
<mpath xlink:href="#circle"/>
</animateMotion>
</use>
|
In the defs element I've added a path element that defines a circle for the rocket to move around. I've also added a rotate transform to the rocket definition so that the rocket will face the right way as it goes around the circle. SVG can turn an image so it always faces the tangent of the line it is following. I chose a circle because my hand-drawn paths made the tangent jump around. Someone with a steadier hand on the tablet might achieve better results. The important thing is that the line the animation follows can be any arbitrary path. Also note that instead of the simpler circle element, I have created the circle using a path with elliptical arcs, so the rocket has a path to follow with a beginning and an end.
To run this example in your browser, download the example code (03_rocket_moving.svg in Download). If you have installed an SVG viewer, click to see this animation.
Okay, so the rocket spinning around gets old after a while. In the fourth example I spice up the scene with a visitor from another world, in a handy-dandy UFO (see Figure 2). This gives me the chance to demonstrate the vanilla animate element as well as its sibling, animateColor.
Figure 2. Unidentified flying vectors
Listing 4 shows all the changes that create the UFO.
Listing 4. UFO (changes only)
<defs>
[...]
<g id="ufo">
<path id="ufo-body" d="M0 50 A100 100
0 0 0 100 50 L100 40 A100 100 0 0 0 0 40 z"/>
<circle id="port-1" class="port" cx="25" cy="45" r="6"/>
<circle id="port-2" class="port" cx="50" cy="45" r="6"/>
<circle id="port-3" class="port" cx="75" cy="45" r="6"/>
</g>
<path id="back-and-forth" d="M100 50 L700 50 z"/>
</defs>
<use xlink:href="#ufo">
<animateMotion dur="50s" repeatCount="indefinite">
<mpath xlink:href="#back-and-forth"/>
</animateMotion>
<animateColor xlink:href="#port-1" dur="10s"
repeatCount="indefinite" attributeName="fill"
values="red;green;blue;red" begin="ufo.load"/>
<animateColor xlink:href="#port-2" dur="10s"
repeatCount="indefinite" attributeName="fill"
values="green;blue;red;green" begin="ufo.load"/>
<animateColor xlink:href="#port-3" dur="10s"
repeatCount="indefinite" attributeName="fill"
values="blue;red;green;blue" begin="ufo.load"/>
</use>
[...]
|
In the defs, I've added a ufo formed from simple SVG arcs and circles, in order to avoid another huge block of path statements from the tablet. I've also added a path to follow for moving back and forth -- a simple line. The closing z closes the path so the UFO has something to follow back to its starting point. In the body, I have a more complex use element than before which contains four different animation elements: an animateMotion similar to what you've seen with the rocket, then three animateColor blocks. Interestingly, the animateColor elements do not apply to the ufo directly (which would be the default), but instead target the UFO's individual portholes by using xlink:href attributes. I've also tied the start of each animateColor to the loading of the UFO's main element.
To run this example in your browser, download the example code (04_ufo.svg in Download). If you have installed an SVG viewer, click to see this animation.
The fifth example adds user interaction, still through declarations. SVG supports all of the mouse events you expect but also has support for keyboard events -- even for specific key events, which is what I've chosen to demonstrate here. Each letter of the alphabet triggers a rocket headed for space (see Figure 3). Time to defend your home planet from the UFO invader!
Figure 3. Missile defense
For this example I remove the transform attribute from the rocket definition, because the rocket will no longer be going in circles, and I remove the definition for the circle. No other changes to the defs are needed. All the action this time is in the body, with 26 variations on a theme (see Listing 5).
Listing 5. Rockets versus UFOs (changes only)
<use xlink:href="#rocket" x="4%" y="85%" display="none">
<set id="showa" attributeName="display" to="inherit"
dur="5s" begin="accessKey(a)"/>
<animate dur="5s" begin="showa.begin" attributeName="y"
from="600" to="-100"/>
</use>
|
Each variation uses the same rocket I defined earlier, but ties it to a different x coordinate and an alphabetic keyboard event. When the viewer presses a key, it triggers the set element, which makes the rocket visible at the bottom of the screen. Notice how an ordinary animate element is tied to the start of the set event. This demonstrates how events can trigger other events. If you want chained events, the second event can be triggered by the end of the set event, rather than the beginning.
To run this example in your browser, download the example code (05_rocket_defense.svg in Download). If you have installed an SVG viewer, click to see this animation. Remember that you need to press a letter key or keys to trigger the rocket motion; depending on your computer's speed, you might experience a slight delay before the rockets appear.
The final example completes your tour of declarative animation scripting in SVG with the animateTransform element. This example shows five rocks, or groups of rocks, appearing in the center of the page, hurling out toward the viewer and disappearing off the edges (see Figure 4).
Figure 4. Rocks coming right at you
This effect requires the animations both to nest and to influence one another. The additive="sum" attribute allows the effect of the various transforms to be cumulative. The first inner transform rotates each rock on its own axis, so that the rocks appear to be spinning as they approach the viewer. The second inner transform scales each rock so it grows (simulating the approach). Both of these transforms are applied to the rock's path, which I pull in with the use element. The outer transform, applied to the entire grouping, moves the rock out toward an edge of the view and off-screen.
Listing 6 shows only one group of animations, but the others are similar, with different points to move offscreen to, and tweaks to their starting time and duration, to mix things up. Most of the line data in Listing 6 is snipped for brevity.
Listing 6. Asteroids! (changes only)
<defs>
[...]
<path id="rock1" d="M-8 -21 L-9 -21 L-15 -21 [...] />
<path id="rock2" d="M19 -15 L18 -17 L14 -20 L12 [...] />
<path id="rock3" d="M-17 -20 L-18 -20 L-19 -20 [...] />
<path id="rock4" d="M11 -14 L11 -15 L10 -15 [...] />
<path id="rock5" d="M14 -30 L13 -30 L12 -29 [...] />
</defs>
[...]
<g>
<use xlink:href="#rock1">
<animateTransform additive="sum" attributeName="transform"
type="rotate" from="0" to="360" dur="6s"
repeatCount="indefinite"/>
<animateTransform additive="sum" attributeName="transform"
type="scale" from="0.1" to="6.0" dur="6s"
repeatCount="indefinite"/>
</use>
<animateTransform additive="sum" attributeName="transform"
type="translate" from="600,400" to="1400,-200" dur="6s"
repeatCount="indefinite"/>
</g>
[...]
|
To run this example in your browser, download the example code (06_asteroids.svg in Download). If you have installed an SVG viewer, click to see this animation.
"Simple things should be declarative. Complex things should be procedural." --Adam Bosworth
Declarative scripting in SVG has its limits. For collision detection and real keyboard navigation, you need to add procedural JavaScript. There was talk of adding a constraint feature to SVG 1.2 but it wasn't adopted, so you need to code constraints procedurally. Adding new objects also requires scripting. Like HTML, SVG adds methods to the DOM interface for more advanced uses. Of course, you can use normal XML DOM methods as well. I think SVG is close to its tipping point, where use of SVG will grow rapidly. At the time of this writing, the latest beta of Firefox doesn't support declarative animation, but the Mozilla team is working on it. The effect once SVG is built into browsers will be huge. New tools to generate or view SVG appear all the time. The future is brighter than a rocket's red glare.
| Description | Name | Size | Download method |
|---|---|---|---|
| Example SVG code | x-matters42-examples.zip | 14 KB | HTTP |
| Example HTML files | x-matters42-html-examplefiles.zip | 2 KB | HTTP |
Information about download methods
Learn
-
Scalable Vector Graphics (SVG) 1.1 Specification: Read the current W3C Recommendation.
-
SVG.org: Check out this community Web site for SVG users, developers, and enthusiasts.
-
Synchronized Multimedia: Learn more about SMIL at the W3C's Interaction domain.
-
SVG Programming: The Graphical Web
by Kurt Cagle (Apress, 2002): This is a comprehensive guide to SVG programming.
-
"XML Matters: Program with SVG" (developerWorks, April 2005): Read David Mertz's previous XML Matters column, which introduces SVG.
- "Introduction to Scalable Vector Graphics" (developerWorks, March 2004): This tutorial by Nicholas Chase introduces the concepts necessary for building SVG documents, including basic shapes, paths, text, painting models, animation, and scripting.
- "Add interactivity to your SVG" (developerWorks, August 2003): Get a good roundup of SVG interaction techniques with this article by Brian Venn.
- "Interactive, dynamic Scalable Vector Graphics" (developerWorks, June 2003): Find out how to use JavaScript to dynamically control the content and appearance of a floor-plan image rendered using SVG.
- "Bring Scalable Vector Graphics to life with built-in animation elements" (developerWorks, June 2003): Brian Venn shows you how to apply the five flavors of SVG animations to your SVG documents.
-
Adobe's SVG Zone: Find many SVG resources.
- XML Matters column: Find other articles by these authors.
Get products and technologies
-
Adobe SVG Viewer: Download the viewer that was used to test the examples in this article.
-
Batik: Try this Java™ technology-based SVG toolkit from the Apache-XML project.
-
Compound XML Document Editor: This standards-based, model-driven editor for mixed-namespace XML documents includes support for SVG and SMIL.

Dethe Elza's favorite job title has been Chief Mad Scientist. Dethe can be reached at delza@livingcode.org. He keeps a blog mainly about Python and Mac OS X at http://livingcode.blogspot.com/ and writes programs for his kids. Suggestions and recommendations on this column are welcome.

David Mertz is a great believer in open standards, and is only modestly intimidated by verbosity. David may be reached at mertz@gnosis.cx; his life pored over at http://gnosis.cx/dW/. Suggestions and recommendations on this, past, or future columns are welcomed. Check out David's book Text Processing in Python.



