Back

Replacement Animation

As I'm sure you figured after doing the slide show and ad rotator projects, doing animation by replacing images is relatively simple.  Animation on the web is very much like those flip books you created as a kid.  You know, you place an individual image on the corner of each page in the book then flip through the book rapidly to see the animation.  If you flip rapidly enough, the animation is smooth.  If you don't flip rapidly enough, the animation is jerky.

Well, doing replacement animation with JavaScript is no different.  The general process is to create an array of images to cycle through, then swap the images fast enough so that the user perceives motion.  Just remember, there really isn't any motion taking place.  You are simply controlling which frame the user is currently viewing.

Before we begin, we'll need an image set to work with.  You can download a set I've prepared here.  This file contains 24 frames of a baseball spinning.  The files are compressed together in a ZIP archive so you'll need a tool to extract them.  You can get a trial version of WinZIP here.  Once you get a ZIP utility, extract the files to an images folder where you'll store the images.

It's customary to name the individual frames in an image set with the same prefix and then a frame number.  The baseball.zip file contains files named ball0.gif through ball23.gif.  This construct works nicely as we'll create an array to hold the images.  The good news is that we won't have to declare each individual image object.  Rather, because the names of the files are indexed, we can create a simple loop that does all of the work for us.  Finally, we'll make use of the rotate() function that we wrote for the ad rotator and set the delay for setTimeout() to a very small number.  This allows us to achieve that flicker-free, smooth animation that everyone likes.

Here's the code to get us going:

<html>
<head>
<title>Replacement Animation</title>
</head>
<body>
<p><img name="ball" border="0" src="images/ball0.gif" width="256" height="256"></p>
</body>
</html>

All this code does is set up an <img> element to hold the frames of our animation.  I've given it a name of "ball" but it could have been anything.  OK, now let's retrieve our images and store them in an array.  We'll use a for loop as we know how many frames there are.  Start a <script> element in the head and then add this code:

<script language="JavaScript">
var imgArray = new Array();
for (i=0; i<24; i++){
imgArray[i] = new Image();
imgArray[i].src = 'images/ball' + i + '.gif';
}
</script>

That's certainly a lot easier than typing out var ball1 = new Image(), ball1.src = 'images/ball1.gif' for each image.  The noteworthy part of the above loop is the way that the index of the loop is contained within the name of the image file.  When we set the src property, we concatenate the ball plus the image number plus .gif.  The result is a valid image.

Now it's time to add our rotate function.  Modify your script so that it looks like this:

<script language="JavaScript">
var imgArray = new Array();
for (i=0; i<24; i++){
imgArray[i] = new Image();
imgArray[i].src = 'images/ball' + i + '.gif';
}
var counter = 0;
function rotate(){
if(counter>imgArray.length-1)
counter = 0;
document['ball'].src = imgArray[counter].src;
counter++;
setTimeout('rotate()',60);
}
</script>

The rotate() function is identical to the one used for the ad rotator only we set the delay for setTimeout() to 60 milliseconds.  60 milliseconds is roughly equivalent to 16 frames per second. To get the frames per second, simply divide 1000 by 60 (in this case you'll actually get 16.667).  Anything higher than about 15 frames per second results in smooth animation.  Anything lower and the transitions between the frames may become visible.  Just for your information, movies are usually shot at around 24 frames per second and television is usually 30 frames per second.

The very last thing to do is to get the animation started.  We'll use the onLoad event in the <body> element to get us started but it could have just as easily been a button click.  Here's the finished code:

<html>
<head>
<title>Replacement Animation</title>
<script language="JavaScript">
var imgArray = new Array();
for (i=0; i<24; i++){
imgArray[i] = new Image();
imgArray[i].src = 'images/ball' + i + '.gif';
}
var counter = 0;
function rotate(){
if(counter>imgArray.length-1)
counter = 0;
document['ball'].src = imgArray[counter].src;
counter++;
setTimeout('rotate()',70);
}
</script>
</head>
<body onLoad="rotate()">
<p><img name="ball" border="0" src="images/ball0.gif" width="256" height="256"></p>
</body>
</html>

You can see it in action on the Source Code Page.

There are some obvious drawbacks to using replacement animation.  First, in order for the animation to run smoothly, you'll want to make the changes in between the frames minimal.  Obviously, the next frame shouldn't be very different from the previous frame.  The result, of course, is that you'll need a lot of images, each of which must be downloaded before the animation even starts.  Even this simple animation that contains 24 images only lasts a few seconds before we cycle through again.  And the total file size - about 500Kb.  That makes for slow downloading.

The second obvious drawback is that your animation is confined within the <img> element's boundaries.  The size and position of the element is fixed.  Later, when we learn Dynamic HTML, we'll see how we can break out of the boundaries of the box and actually move the image around on the screen.  That's coming very soon!