Note: This isn't an overly technical article and is more of a detailed introduction to the power of SVG and it's animation capabilities than anything else. To get started with SVG, you'll first need to download this from Adobe.
Introduction
The easiest way to think of SVG is as a text (XML) - based Flash, but there's a lot more to it than just that. SVG has been a W3C specification since September 4th, 2001 and it has started to get a lot of backing from the industry (viz: Corel, Adobe, Microsoft and well as a bunch of OSD applications) lately. Currently, you'll need a plugin for your browser to view SVG files. When will MS IE natively support this standard is anyone's guess...
There are a couple of ways to package SVG files, the primary ways being as a standalone file or embedded inside an HTML file using the <EMBED>
tag. With SVG you can draw primitive shapes like circles, rectangles and lines as well as create complex animations based on time or triggered by events.
SVG primitives
So, what elements are we going to use in this article and what do they look like?
Circle
<circle cx="100" cy="100" r="25" fill="black" stroke="black" />
Rectangle
<rectangle x="100" y="100" width="50" height="50" fill="black"
stroke="black" stroke-width="1"/>
SVG doesn't have a square element per se, but the <rectangle>
is more than sufficient.
Text
<text x="100" y="100" font-size="20pt">The Code Project</text>
Line
<line x1="100" y1="100" x2="200" y2="100" />
The "1" and "2" type attributes are the start and end points.
Mapping out the animation
Instead of doing some boring animation to show what SVG can do, we'll construct a fairly detailed interactive demo for CodeProject. With this in mind, let's review some of the ways in which animation can work within SVG.
How animation works
Here's a quick demo to get this section started. Given the rectangle example, this SVG will initially render a small rectangle that will get larger and larger:
<rect x="100" y="100" width="50" height="50" fill="black" stroke="black"
stroke-width="1">
<animate attributeName="width" attributeType="XML" begin="0s" dur="4s"
fill="freeze" from="50" to="250" />
<animate attributeName="height" attributeType="XML" begin="0s" dur="4s"
fill="freeze" from="50" to="250" />
</rect>
If you have a look through the code, you'll see how simple it really is. The main thing to note is that the animation is declarative. By nesting an <animate/>
element inside a shape
element you can start to create more and more complex animations without writing any code. The last point here, is that the animations are accumulative. Further on, we'll see some examples of this.
As I said earlier on, animations can be started based on two things: time and events. Here are some of the main events that you'll come across most often:
click
mouseover
mouseout
mousemove
begin
(an important event of animation elements)
load
(actual rendering of the element)
While the first four should be immediately obvious to most programmers, the last two probably require a brief explanation...
"begin
" signifies that an animation has started. This can be useful when you need to string together various animations as only one animation needs to fire the "begin
" event and the rest can listen to that. A sort of chain reaction. Here's what I mean:
<rect x="100" y="100" width="50" height="50" fill="black" stroke="black"
stroke-width="1" id="rect1">
<animate attributeName="width" attributeType="XML" begin="4s" dur="4s"
fill="freeze" from="50" to="250" restart="whenNotActive"
id="firstAnimation" />
<animate attributeName="height" attributeType="XML"
begin="firstAnimation.begin" dur="4s"
fill="freeze" from="50" to="250" restart="whenNotActive" />
</rect>
"load
" signifies that an element has been rendered onto the canvas. What actually seems to happen here, is the event fires when the element has been loaded into a memory-resident buffer and not necessarily when the actual paint
has occurred. If you test this by showing an alert box for this event, you'll see that the element has not yet appeared. Perhaps something to watch out for?
The two primary entities that can raise these begin
and load
events are: the various shape and animation elements respectively, with the animate
elements typically being child elements of shapes.
We can modify the previous animation example to start based on a mouseover
event, like this:
<rect x="100" y="100" width="50" height="50" fill="black" stroke="black"
stroke-width="1" id="rect1">
<animate attributeName="width" attributeType="XML"
begin="rect1.mouseover" dur="4s"
fill="freeze" from="50" to="250" restart="whenNotActive" />
<animate attributeName="height" attributeType="XML"
begin="rect1.mouseover" dur="4s"
fill="freeze" from="50" to="250" restart="whenNotActive" />
</rect>
I've included a new attribute of the rectangle shape called "restart
". All this does is stop the animation from restarting if it is still busy with the initial animation. Try and remove this and you'll see the animation goes into a loop as the mouseover
continually fires.
One of the massively useful features of SVG's animation events is that you can start an animation based on more than one event firing. For instance, we could have changed the begin
attributes of the animation elements to:
begin="rect1.mouseout;rect1.click".
Now, the "begin
" attribute of this rectangle is listening to two events. I've changed the mouseover
to a mouseout
to better differentiate between the two examples. You'll see a number of these more advanced software engineering features within the SVG spec. To wrap up this intro article, here's an SVG file that demos some of the animation capabilities of SVG.