This page is a 'work in progress'. [ToF|User:ToF]
Animation in SVG is defined in the Animation Module of the SVG specification. Animation in SVG conforms to the SMIL specification (Synchronized Multimedia Integration Language) and extends it (SVG is said to be a host language of SMIL).
Here I only focus on procedural animation and not programmatic animation (using a scripting language manipulating the DOM).
In SMIL an animation is an object which defines the evolution of a given attribute of a given object (here an SVG element - path, rect, group...) over time. Multiple animations can control the evolution of particular attribute: for example, one will tell the object to turn for 1 seconde starting at
t=0 and another to move accross the document for 2 secondes starting at later time. So we have this relation:
1:n Element <-------> Animation
For a given animation the element which is controlled is called the 'target' element of the animation.
In fact, two animation controlling the same attribute of the same element can overlap in time: at any particular time there exists a stack of animation applying to a particular attribute, and SMIL defines the order in which each animation is applied.
SVG defines 5 animation elements:
This element is used to animate any scalar attribute or property, such as the
width attribute of an svg:rect element or the CCS property
This elements only controls the position of a SVG element, by telling it to follow a given path
This element controls the animation of color valued attributes and properties.
This element controls the transformation which applies to the target element. It replaces or sums over the
transform attribute of the element.
This element is used to set a particular value for the target attribute during a specified time interval. It is mainly used for animating attributes which do not span a continuous domain, such as boolean values like the
Specifying the target element and property
There are 2 ways to tell which element a given animation will target. The first one is to embed the animation element as a child tag of the element to animate. Here is an example:
<circle cx="100px" cy="100px" r="20px"> <animate attributeName="r" attributeType="XML" begin="1s" dur="2s" from="20px" to="50px"> </circle>
animate element targets the radius (
r) property of the parent
circle element. Starting 1 seconde after the document start, the radius will grow for 2 secondes from 20 pixels to 50 pixels. When nothing else is specified, the animation only applies in its interval of time, here [1-3] secondes; from 0 to 1 seconde and then from 3 seconde and after, the circle's radius is set back to its static attribute value, here 20 pixels.
The other way to specify the target element is to reference it in via an
xlink:href attribute of the animation element. the previous animation could be written this way:
<circle id="balloon" cx="100px" cy="100px" r="20px" /> <animate xlink:href="#balloon" attributeName="r" attributeType="XML" begin="1s" dur="2s" from="20px" to="50px" />
To specify which property or attribute of the target element is controlled, we use the two attributes
attributeName explains itself, it's the name of the controlled attribute.
attributeType tells whether
attributeName is searched among the SVG attributes of the element (
attributeType="XML") or among the CSS properties of the element (
Timing an animation
The first thing to stress is that SMIL (and therefore SVG) animation is 'time-based', as opposed to 'frame-based'. 'Frame-based' animation is something traditional animators are used to, because they actually draw each image of the animation on a separate celluloid sheet, and the timing is related to the rate of images per seconde the camera will capture. When animation is done on a computer, the animator doesn't draw every image but only some key images (or keyframes) and then the animation software creates all the necessary images for him (the so-called in-betweens). That means the animator can focus back to a (real-)time based timing. Each keyframe is positionned on a timeline with real time values (instead of frame numbers). Of course at the end the animation is discrete and there is a fixed number of images computed inbetween two keyframes, but the neat property of specifying keyframes at time position is that the final animation frame rate is scalable and the animator doesn't have to care about it anymore. He just tells the software to produce 24 images each seconde if he targets a theatre film or say 10 images per second for low-bandwith web animation. The animator doesn't need to reposition the keyframes.
Creating the inbetween images on a computer is done by mean of 'interpolation'. Interpolation is a mathematical tool that can reconstruct a the continuous evolution of a parameter given a set of discrete values of this parameter over time.
- which extent of time ?
The first aspect that characterize an animation is the extent of time it applies: when does it begin, when does it end or how long does it run.
Any of the above mentionned [[animation elements|Animation element] accepte the attribute
dur. There are many ways to define a particular point in time and this is what makes SMIL a very rich animation framework (see below). The simplest is to specify a clock-value which syntax is quite intuitive (SPEC).
- which values ? from, to, by
- the pacing ? the time warp function: discrete, linear, spline, paced.
- more: repeating / min, max, event based synchronisation, chaining animations.
The following examples showcase some of the effects that can be achieved using procedural animation in SVG.
- Squiggle , as part of Batik 1.7 has a nearly complete support for SMIL Animation. The examples were all rendered using Squiggle.
- Inkscape ! I used the xml editor to manually add the animation elements for my test. It's a bit more cumbersome than editing the svg file in a text editor, but doing that in Inkscape eases the computation of keyposition (just move the object around and read the position values).
- There is no direct way to specify a ping-pong animation in SVG, that is tell an animation to go back in time when it reaches it's end. To implement this, I see 2 solutions:
- double the duration d of the animation (
durattribute) et apply a scale and a symetry around t=0.5 to the animation function. For exemple the simple linear interpolation defined by
keyTimes="0; 0.5; 1"and
keyPoints="0;1;0". This doesn't work for
pacedanimation though (which make use of an implicit, user-agent dependent animation function).
- copy the original animation (call it e.g.
motion_forward) and swap the
tovalues in the copy. Then specify
begin="motion_forward.end"to tell the backward animation to start right at the end of the forward animation. This should work for every animation type.
- double the duration d of the animation (
The question is: what maps best to a UI ?