J R Sinclair

Animation with SVG and Javascript

Part 1: Drawing the Smiley Face

OK. If you've got a text-editor ready, let's get started. First of all, we need to create an SVG document. Create a new, blank document in your text-editor, and type in the following:

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="400px" height="400px" version="1.1"
     xmlns="http://www.w3.org/2000/svg">

</svg>

Save that as bouncingball.svg or something like that.

Congratulations, you've just created an SVG file. You might be wondering what it was that you just wrote though, so let's go through it step-by-step.

<?xml version="1.0"?>

This bit tells the browser that this is an XML document. XML stands for eXtensible Markup Language. It's probably easiest to think of XML as being the language that SVG is written in, though that's not strictly true.

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

This couple of lines tells the browser where the SVG standard is defined. Theoretically, it allows the browser to check what we've written to see if we followed the standard correctly.

<svg width="400px" height="400px" version="1.1"
     xmlns="http://www.w3.org/2000/svg">

</svg>

This bit actually starts telling the browser about the svg document. In XML everything is done with tags, similar to HTML. The <svg> tag says "The svg starts here," and the </svg> says "The svg stops here."

The <svg> also has some attributes associated with it. They tell the browser that we want the picture to be 400 pixels wide and 400 pixels high, and that we're using SVG version 1.1. The xmlns bit is something to do with XML that we don't really need to worry about now.

That's all very nice, but if you were to open the file with IE or something at the moment, it wouldn't look like much. Let's draw something. Add the following lines after the <svg> tag, but before the </svg> tag.

  <!-- A yellow circle for the smiley face --> 
  <circle cx="30" cy="30" r="30"
          fill="yellow" stroke="black" stroke-width="1"/>

If you open your file in a browser now, you should see a yellow circle. Let's have a look at how it works:

<!-- A yellow circle for the smiley face -->  This line is a comment which explains to anyone reading it what the code is doing.
<circle This bit tells the viewer that we want to draw a circle.
cx="30" This bit tells the viewer to put the centre of the circle 30 pixels from the left edge of the picture. c stands for "centre" and x stands for "X-axis".
cy="30" This bit tells the viewer to put the centre of the circle 30 pixels down from the top edge of the picture.
r="30" This bit tells the viewer that we want the radius of the circle to be 30 pixels.
fill="yellow" This bit tells the viewer to fill the circle with yellow.
stroke="black" This bit tells the viewer to make the outline of the circle black.
stroke-width="1" This bit tells the viewer to make the outline of the circle one pixel thick.
/> Finally, this is a bit of short-hand to write the closing tag. We write /> as a short-cut for ></rect>.

Next, we draw the eyes. These are just two ellipses. The code for them is:

  <!-- The left eye -->
  <ellipse cx="22" cy="22" rx="6" ry="11"
           fill="black"/>

  <!-- The right eye -->
  <ellipse cx="38" cy="22" rx="6" ry="11"
           fill="black"/>

This is pretty similar to the circle. The main difference is the rx and ry. These tell the viewer how wide and how high we want the ellipse to be. rx stands for "x-radius", so, if we want the ellipse to be twelve pixels wide, then we give it a radius of six pixels.

Graphic showing the relationship between rx, ry, cy and cy for an ellipse in svg.

Finally, we need to draw the smile. This is a little bit more complicated than ellipses and cirles, but try not to freak out too much. To make the smile we're going to draw what's called a path. A path can be made up of straight and curvy lines. In this case our smile is made of two arcs. An arc is like a chopped-off bit of an ellipse. Don't worry if it doesn't make a huge amount of sense at first. Here's the code, it goes after the ellipses:

  <!-- The smile -->
  <path d="M15 40
           a16,16 0 0,0 30,0
           a20,20 0 0,1 -30,0"
        fill="black" stroke="black" stroke-width="0" />

The tricky bit is the d attribute. Let's break it up a bit:

M15 40 The M stands for "Move to". So, this part of the code tells the viewer to start the path 15 pixels from the left and 40 pixels from the top.
a16,16 0 0,0 30,0 The a here stands for "arc". The first two numbers (16,16) tell the viewer that we want an arc which has an rx and ry of 16 pixels. The last two numbers (30,0) tells the viewer that we want the end of the arc to be 30 pixels across and 0 pixels down from where we started out (15 40). Finally, the 0,1 tells the viewer whether we want the smile to point up or down.
a20,20 0 0,1 -30,0 This line is pretty similar to the one above. The a says we want an arc; the 20,20 says we want a radius of 20 pixels (this is for the bottom bit of the smile). The arc starts where the last one fishished, so we want this one to finish 30 pixels to the left, where we started. That's what the -30,0 is for.

To make things a bit prettier, let's add a blue border, and grey background. Put this code in before the yellow circle:

 <!-- Rectangle for the border and background -->
 <rect x="0.5" y="0.5" width="399" height="399"
       fill="#CCC;" stroke="navy" stroke-width="1" />

Your picture should now look something like this:

The finished picture with smiley face in the top-left corner

Finally, we need to think about how we're going to make this thing move. If you change the cx and cy attributes to 40 and 40, then the picture looks like this:

If you change the cx and cy attributes of the circle, the face doesn't move with it.

Wouldn't it be nice if there was a way we could group the bits of the face together, so we could just change the location of the group instead of every element? Well, we're in luck because SVG allows us to do just that. After the rectangle, but before the circle, add the following lines of code:

 <!-- A group for the Smiley Face -->
 <g id="smileyFace" transform="translate(3,3)">

Then, after the path element add:

 </g>

This groups together everything between the <g> and the </g> tags. The id attribute lets us give the group a name so we can make it move using javascript later. The transform tells the viewer to move the face down 3 pixels and across three pixels ("translate" in this case basically means "move").

If all has gone well, your file should look something like this:

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="400px" height="400px" version="1.1"
     xmlns="http://www.w3.org/2000/svg">

 <!-- Rectangle for the border and background -->
 <rect x="0.5" y="0.5" width="399" height="399"
       fill="#CCC;" stroke="navy" stroke-width="1" />

 <!-- A group for the Smiley Face -->
 <g id="smileyFace" transform="translate(3,3)">

  <!-- A yellow circle for the smiley face --> 
  <circle cx="30" cy="30" r="30"
          fill="yellow" stroke="black" stroke-width="1"/>

  <!-- The left eye -->
  <ellipse cx="22" cy="22" rx="6" ry="11"
           fill="black"/>

  <!-- The right eye -->
  <ellipse cx="38" cy="22" rx="6" ry="11"
           fill="black"/>

  <!-- The smile -->
  <path d="M15 40
           a16,16 0 0,0 30,0
           a20,20 0 0,1 -30,0"
        fill="black" stroke="black" stroke-width="0" />
 </g>

</svg>

Next, we want to make the picture move…