Although the HTML5 canvas tag might not replace Flash as a mechanism for implementing games and animations in the browser, it is reasonably easy to add animation to a canvas image. The key is to use the animation features already built into the browser.

Basic structure of the animation loop in HTML5 canvas

An animation generally requires a special organization called an animation loop. The basic structure of the animation loop works the same in any language:

  1. Initialization.

    Create the assets, including the background and any of the objects you will be using. Objects that will be manipulated in real time are normally called sprites. Generally, this is done when the program first runs, to save time during the main execution. You may also set constants for image size, display size, frame rate, and other values that will not change during the execution of the game.

  2. Determine a frame rate.

    Animations and games work by calling a function repeatedly at a prescribed rate. In JavaScript, you typically use the setInterval() function to specify a repeated function. The frame rate indicates how often the specified function will be called. Games and animations typically run at frame rates between 10 and 30 frames per second. A faster frame rate is smoother, but may not be maintainable with some hardware.

  3. Evaluate the current state.

    Each sprite is really a data element. During every frame, determine if anything important has happened: Did the user press a key? Is an element supposed to move? Did a sprite leave the screen? Did two sprites conk into each other?

  4. Modify sprite data.

    Each sprite generally has position or rotation data that can be modified during each frame. Usually this is done through transformations (translation, rotation, and scale), although sometimes you may switch between images instead.

  5. Clear the background.

    An animation is really a series of images drawn rapidly in the same place. Usually, you'll need to clear the background at the beginning of each frame to clear out the last frame's image.

  6. Redraw all sprites.

    Each sprite is redrawn using its new data. The sprites appear to move because they're drawn in a new location or orientation.

Creating the constants of an animation feature in HTML5 canvas

Building a program that rotates an image inside a canvas requires several batches of code. The first job is to set up the various variables and constants that describe the problem. The following code is created outside any functions because it describes values that will be shared among functions:

  var drawing;
  var con;
  var goofyPic;
  var angle = 0;
  CANV_HEIGHT = 200;
  CANV_WIDTH = 200;
  SPR_HEIGHT = 50;
  SPR_WIDTH = 40;

The drawing variable will refer to the canvas element. The con variable will be the drawing context, goofyPic is the image to be rotated, and angle will be used to determine how much the image is currently rotated. The other values are constants used to describe the height and width of the canvas as well as the sprite.

Deploying the animation in HTML5 canvas

Use the body onload mechanism to start up some code as soon as the page has finished loading. However, the page now has two functions. The init() function handles initialization, and the draw() function will be called repeatedly to handle the actual animation. Here's the code in the init() function:

  function init(){
    drawing = document.getElementById("drawing");
    con = drawing.getContext("2d");
    goofyPic = document.getElementById("goofyPic");
    setInterval(draw, 100);
  } // end init

The job of the init() function is to initialize things. In this particular example, various elements (the canvas, the context, and the image) are loaded into JavaScript variables, and the animation is set up. The setInterval() function is used to set up the main animation loop. It takes two parameters:

  • A repeatable function: The first parameter is the name of a function that will be called repeatedly. In this case, the draw function will be called many times.

  • A delay value: The second parameter indicates how often the function should be called in milliseconds (1/1000 of a second). A delay of 100 will create a frame rate of 10 frames per second. A delay of 50 will cause a frame rate of 20 frames per second, and so on.

Giving animation to the current frame in HTML5 canvas

The draw() function will be called many times in succession. In general, its task is to clear the frame, calculate new sprite states, and redraw the sprite. Here's the code:

  function draw(){
    //clear background
    con.fillStyle = "white";
    con.fillRect(0, 0, CANV_HEIGHT, CANV_WIDTH);
    //draw border
    con.strokeStyle = "red";
    con.lineWidth = "5";
    con.strokeRect(0, 0, CANV_WIDTH, CANV_HEIGHT);
    //change the rotation angle
    angle += .25;
    if (angle > Math.PI * 2){
      angle = 0;
    //start a new transformation system;
    con.translate(100, 100);
    //draw the image
       SPR_WIDTH/-2, SPR_HEIGHT/-2, 
 } // end draw    

While the code may seem a little involved, it doesn't really do anything new:

  1. Clear the background.

    Remember that animation is repeated drawing. If you don't clear the background at the beginning of every frame, you'll see the previous frame drawings. Use the context's clearRect() function to draw a fresh background, or one of the other drawing tools to use a more complex background image.

  2. Draw any nonsprite content.

    For example, you can use strokeStyle, lineWidth, and strokeRect() to build a red rectangular frame around the canvas. Note that the CANV_HEIGHT and CANV_WIDTH constants refer to the current canvas size.

  3. Modify the sprite state.

    To modify the rotation angle of the image in the example, the variable called angle was created outside the function. (It's important that angle was created outside the function context so it can retain its value between calls to the function.) You can then add a small amount to angle every frame.

    Whenever you change a variable (especially in a virtually endless loop like an animation), you should check for boundary conditions. The largest permissible angle value (in radians) is two times pi. If the angle gets larger than that, it resets to zero.

  4. Build a transformation. Set up a new transformation with the save() method, and use the rotate() and translate() functions to transform a temporary coordinate system.

    Many animations are really modifications of a transformation. The image isn't changing, just the transformation that contains the image.

  5. Draw the image at the center of the new transformation.

    The drawImage() command draws the image based on the top-left corner of an image. If you draw the image at (0, 0) of the new transformation, the image will appear to rotate around its top-left corner. Usually, you'll want an image to rotate around its center point. Simply draw the image so its center is at the origin. Set X to zero minus half the image's width, and Y to zero minus half the image's height.

  6. Close the transformation. Use the restore() method to finish defining the temporary coordinate system.