- SVG and the DOM
- Simple Animations
- Modifying SVG from JavaScript
- Browser Support
Simple Animations
The big difference between SVG and the canvas is the fact that SVG is declarative, whereas the canvas is imperative. If you're using JavaScript for both, this distinction isn't particularly important. In either case, you're using an imperative language for the animations.
JavaScript isn't the only option, however. SVG includes support for animations directly via SMIL and some SMIL extensions. The two simplest tags used for animation in SVG are animateTransform and animateColor. We can use these tags to extend the previous example, making the circle containing text move and change color:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" width="100pt" height="500pt"> <g> <animateTransform attributeName="transform" attributeType="XML" type="translate" from="0" to="450" begin="0s" dur="5s" fill="freeze"/> <animateTransform attributeName="transform" attributeType="XML" type="translate" from="450" to="0" begin="5s" dur="5s" fill="freeze"/> <circle cx="50pt" cy="50pt" r="45pt" fill="red" stroke="black" > <animateColor attributeName="fill" attributeType="CSS" from="red" to="green" begin="0s" dur="10s" fill="freeze" /> </circle> <foreignObject x="20pt" y="20pt" width="60pt" height="60pt"> <body xmlns="http://www.w3.org/1999/xhtml"> <p style="text-align: center">HTML text in an SVG circle!</p> </body> </foreignObject> </g> </svg>
The first thing that you'll notice about this example is the addition of the <g> tag, which defines a group of elements in an SVG document. The animateTransform tag operates on the element that contains it, modifying some aspect of that element's coordinate-transform matrix. We need to add the grouping element so that the transform has something on which to act.
The transformation itself is quite simple; it defines a change of some attribute of the document over time. The attributeName attribute specifies that these two animations modify the coordinate transform. As I mentioned earlier, SVG elements use a PostScript drawing model, and each level of nesting in the tree can apply a new coordinate transform.
In this example, we're defining two animations on the coordinate transform. One, which runs from 0 seconds to 5 seconds, transforms the translation from 0 to 450. The second, running from 5 seconds to 10 seconds, translates it back. The end result is that the circle and the text move across the screen and then back over a period of 10 seconds.
The other transform is inside the <circle> tag. This transform changes the fill attribute of the parent element's CSS from red to green over the same 10-second period.
Notice that both of these tags specify fill="freeze". At the end of the animation, the animated property will remain in its current state rather than being reset. The color will remain green. Setting this attribute to "remove" instead would cause it to gradually become green, jumping back to red as soon as the animation ended.
Coordinate transforms are very powerful, but they're far from the simplest way of defining motion. We can achieve something very similar with the animateMotion tag. This example defines an animation along a path:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="full" width="500pt" height="100pt"> <path id="path1" d="M0,0 L450,0 L0,00" fill="none" stroke="none"/> <g id="example"> <circle cx="50pt" cy="50pt" r="45pt" fill="red" stroke="black" id="circle" /> <foreignObject x="20pt" y="20pt" width="60pt" height="60pt"> <body xmlns="http://www.w3.org/1999/xhtml"> <p style="text-align: center">HTML text in an SVG circle!</p> </body> </foreignObject> <animateMotion dur="10s" repeatCount="indefinite" rotate="none" > <mpath xlink:href="#path1"/> </animateMotion> </g> </svg>
This example begins by defining the path. Paths in SVG aren't quite what you'd expect from an XML format. They contain a single attribute (d), which describes the path using something that looks very much like a sequence of PostScript commands. In this example, the path consists of a move (M) command and two line (L) commands.
The lines will be used by the animation, but we need to make certain that they are not drawn, so we explicitly set fill and stroke to none. The path is then referenced by the mpath child of the animateMotion tag. Note that we need to import the xlink namespace for references to other parts of the document to work. We do this by specifying the xlink namespace in the xmlns:xlink attribute at the top, indicating that everything with the xlink: prefix should be treated as coming from the xlink namespace.
This animation moves the group of objects along the path over a period of 10 seconds, and then repeats forever. The rotate attribute is used to indicate that no rotation should be performed. In this animation, the path is just used to define where the upper-left corner of the shape should be. If you set the rotate parameter to auto, the gradient of the line at that point will be used to define the top edge of the shape. This option lets you draw shapes along curved paths and have them automatically follow the contours of the path.