Declarative animation in SVG

Before getting into this topic, there are several important things that need to be explained:
  1. By declarative animation, we mean animation that is done with markup rather than script.
  2. The term SMIL evokes different meanings in different audiences. Some have used it to refer to the subset of SMIL borrowed into and then expanded within SVG. Others use it to refer to the much broader context of SMIL within the SMIL working group of the W3C. The latter is more correct and the former usage has sometimes been known to evoke strong emotions that might surprise the casual speaker! The term "SVG animation" is more frequently used nowadays to refer to declarative animation in SVG
  3. While all major browsers have implemented some degree of declarative animation in SVG, Microsoft has indicated that IE9 will not, at least at first,  support SVG animation. The SVG Working Group and other working groups within W3C like the CSS WG and the HTML WG seem to be interested in harmonizing the animation within CSS so that much of what is now possible within SVG could also be applied to HTML. It sounds good, in principle, though how scripts which rely on animation being a part of the DOM would react to discovering it now tucked away in some facet of CSS4 is a bit puzzling to some of us who have not been closely involved in these discussions.
  4. To work with this material you'll need a browser that handles it well. Opera and the ASV plugin for IE are the best implementations, followed by Firefox 4 beta. Chrome is slightly ahead of Safari at this time. Check to see if this example works in your browser. If not, change browsers for this section.
  5. There are two JavaScript libraries that provide partial support for SVG animation Fake SMIL and SmilScript. At SVG Open 2010, the Microsoft team recently demonstrated this example running in IE9 beta with the use of SMILScript.
  6. Almost all attributes of SVG objects can be animated declaratively.
  7. Not all animation can be done declaratively (at least yet) in SVG. Script is still far more powerful and we will later consider examples that cannot be done with SVG's declarative methods.
  8. This instructor is very fond of declarative animation! It is easy to use and appears to me (based on my own experience and that of the students I've seen use it for several years) to cut development time down by considerable fractions.
After taking a quick read of the first sections of  the SVG Primer's treatment of the animate tag, try out the following simple example, and let's start from there. I'll try embedding it here in the HTML (using an <embed> tag), but I'll put a picture of it with a link to the working example next to that in case your browser can't see it:
Snapshot of animated ellipse
animated ellipse
(snapshot)
<ellipse id="E" cx="90" cy="90" rx="30" ry="40" fill="#448">
<animate attributeName="rx" dur="5s" values="20;90;20" repeatCount="indefinite"/>
<animate attributeName="ry" dur="5s" values="30;60;30" repeatCount="indefinite"/>
</ellipse>

In the above, we have put two animate tags inside the ellipse. One controls the width and the other the height of the ellipse. The attributes in this example control the following:
For those of you who have written scripted animation in JavaScript, using setTimeout or setInterval, you will probably agree that this "declarative" approach through markup is quite nice. 

Just to give you a bit more exposure to the basic concepts, let's try another. We'll duplicate the ellipse from above and shift its position a bit. Then let's vary the values attribute of the second ellipse so that as one ellipse expands the other contracts. I've added a rectangle (with rounded corners) and applied a bit of transparency to the example for fun.
two ovals inversely correlated in size
animated ellipses
(snapshot)
<rect x="100" y="85" rx="12" height="30" width="150" fill="purple" stroke="black" stroke-width="3" />

<ellipse cx="100" cy="100" rx="30" ry="40" fill="#448" opacity=".75" stroke="black" stroke-width="3">
<animate attributeName="rx" type="rotate" dur="5s" values="10;70;10" repeatCount="indefinite"/>
<animate attributeName="ry" type="rotate" dur="5s" values="30;60;30" repeatCount="indefinite"/>
</ellipse>
<ellipse cx="250" cy="100" rx="30" ry="40" fill="#448" opacity=".75" stroke="black" stroke-width="3">
<animate attributeName="rx" type="rotate" dur="5s" values="70;10;70" repeatCount="indefinite"/>
<animate attributeName="ry" type="rotate" dur="5s" values="60;30;60" repeatCount="indefinite"/>
</ellipse>

In these examples, the timing associated with all attributes has been the same: 5 seconds. Let's consider what happens when we vary that interval for different attributes. In this example, we add a stroke-dasharray to the ellipses and let the center of the second ellipse, as well as the width of the rectangle vary (in synchrony with one another). This demonstrates that de-synchronizing and synchronizing can yield rather fascinating effects! I would posit that we tend to overlay causal explanations of what we see, when in fact, only covaration is present. The scientific study of the perception of illusions is likely to have some great advances in coming years due to the reduced difficulty of creating such demonstrations.

While the previous example, using stroke-dasharray, appears to present a bit of rotation to the object, this is simply because the circumference of the ellipse is changing (as rx and ry change), and because dash-arrays are allocated in terms of absolute units (pixel widths), the number of  dash segments needed to cover the ellipse also varies. We might also experiment with the illusion of rotation in the following way: by animating the dash-offset attribute. (The following example seems only to work in Chrome, Opera and IE/ASV, with FF4 beta not handling the animation and Safari being rather unhappy with the colors of the gradient. )

ellipses with animated dash-offset
animated dashoffset (snapshot)
<ellipse cx="140" cy="100" rx="50" ry="50" fill="url(#Gold)" stroke="url(#Go)" 
stroke-width="18" stroke-dasharray="12,12" >
<animate attributeName="stroke-dashoffset" repeatCount="indefinite"
values="24;0" dur="0.5s" />
</ellipse>

It turns out that there is a better way of rotating objects than by animating the stroke. <animateTransform> can be used to change either the scale, position or rotation of an object.

Now let's play a bit more with the positioning of these ellipses by letting them follow a curve, using the <animateMotion> tag.