How to animate canvas graphics (HTML)

[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]

The canvas element is a drawable region on your HTML document that you can use JavaScript for generating graphics such as animations, graphs, and games. This topic gets you started by describing the steps needed to animate a basic drawing using the canvas element.

Prerequisites

This topic assumes that you:

  • Can create a basic Windows app using JavaScript that uses the Windows Library for JavaScript template.
  • Have a basic understanding of HTML and JavaScript.

For instructions on creating your first Windows app using JavaScript, see Create your first Windows Store app using JavaScript. For instructions on using the WinJS template, see How To Obtain and Use the WinJS Toolkit.

Instructions

Step 1: Timing the animation

Using the requestAnimationFrame method, you begin an animation by specifying a function to call (callback) whenever it's time to update your animation for the next repaint:

requestAnimationFrame(animationFunction);

requestAnimationFrame takes page visibility and the display's refresh rate into account to determine how many frames per second to allocate to the animation (that is, call animationFunction).

Our JavaScript example draws an animated circle that moves in a spiral motion around a larger circle.

requestAnimationFrame(draw);

Here is our animation (results may vary, faster hardware results in more closely paced circles):

An example of a spiral circle drawn by a canvas animation.

Step 2: Drawing the image

  1. Clear the canvas

    You'll need to clear the canvas before drawing each frame.

    There are various methods for clearing a canvas, or parts of an image, such as clearing certain areas using the globalCompositOperation property or by clipping paths using the clip method. The simplest way to clear a canvas is to use the clearRect method.

    In our example the clearRect method is used to clear the entire canvas, but to make it easier to see the effects of drawing our image, the clearRect method is commented out. If this line of code were uncommented, you would see a single circle spiraling around in a larger circular orbit and its trail would be cleared before each frame is drawn.

    // The clearRect method clears the entire canvas.
    context.clearRect(0, 0, 160, 160);
    
  2. Save the canvas state

    When drawing your image you might change some of the settings such as styles or transformations. If you want to use the original settings when you begin each redraw of the image, you can use the save method.

    The save and restore methods are used to save and retrieve the canvas state on a stack. The canvas state consists of all of the styles and transformations that have been applied. Every time the save method is called the current canvas state is saved on the stack. The restore method returns the latest saved state from the stack.

    In our example, we use the save method just prior to setting some transforms to draw and move the animated circle.

    // Save the canvas state.
    context.save();
    
  3. Draw the image

    While drawing the image to the canvas, you can use two transformations to make changes to your image; the translate and the rotate methods.

    The translate method is used to move the canvas and its origin to a different point in the canvas grid:

    translate(x, y)
    

    This method takes two arguments; x is the amount the canvas is moved to the left or right, and y is the amount it's moved up or down.

    It's a good idea to save the canvas state before doing any transformations as it is easier to call the restore method than having to do a reverse translation to return the canvas to its original state. The translate method allows you to place the image anywhere on the canvas without having to manually adjust coordinates.

    The rotate method is used to rotate the canvas around the current origin. This method has only one parameter and that’s the angle the canvas is rotated, measured in radians.

    rotate(angle)
    

    The rotation moves clockwise, and the rotation center point is always the canvas origin (the top left corner). To move the center point you’ll need to move the canvas using the translate method.

    In our example we're going to alternate a few calls to the translate and rotate methods. The first call to the translate method will center the animation on the canvas.

    Next, we make two sets of calls to the rotate and translate methods. The first calls to the rotate and translate methods will produce a small circle that is drawn around the canvas in a large loop. The second set of calls will produce a small circle that is drawn in a much smaller orbit.

    The canvas size is set to 160 pixels high and 160 pixels wide, so we’ll set the translate method’s x and y coordinates equal to 80 so that our overall animation is centered in the canvas.

    // centers the image on the canvas             
    context.translate(80, 80);
    

    We begin our first call to the rotate method by using the date object to calculate the rotate method's parameter. This parameter is the angle that the canvas is to be rotated.

    var time = new Date();
    context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
    

    Note that the value used to calculate getSeconds is 60 and the value to calculate the getMilliseconds is 60,000.

    The translate method moves the x coordinate which moves the rotating circle around the canvas in a large orbit.

    // Translate determines the size of the circle's orbit.
    context.translate(50, 0);
    

    This is the effect of the first rotate and translate methods:

    A large circle with no loops.

    The next two calls to the rotate and translate methods create a smaller orbit of looping circles.

    // Rotate causes the circle to move in a small orbit.
    context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
    
    // Translate determines the size of the orbit.
    context.translate(0, 5);
    

    Note that in calculating the angle for the second rotate call, the value used to calculate getSeconds is 6 and the value to calculate the getMilliseconds is 6,000.

    If the first rotate and translate methods are commented out here is what our second rotate and translate methods would draw:

    A looping circle.

    After all the repositioning has been set, the circle is drawn on the canvas.

    // This draws the repositioned circle
    context.beginPath();
    context.arc(5, 5, 4, 0, Math.PI*2, true); 
    context.stroke();
    
  4. Restore the canvas state

    We saved the canvas state earlier, in step b, so now we reset the canvas state for the next frame to be drawn.

    // Restores the canvas to the previous state
    context.restore();
    

Complete Examples

Animated graphic

This JavaScript example draws an animated circle that moves in a spiral motion around a larger circle.

window.onload = init;
  
// As an optimization, make "context" a global variable that is only set once.
var context;
  
function init(){
  context = document.getElementById('canvas').getContext('2d');    
  window.requestAnimationFrame(draw);
} // init

function draw() {
  // Save the canvas state.
  context.save();         
  
  // context.clearRect(0, 0, 160, 160);

  // centers the image on the canvas             
  context.translate(80, 80); 
  
  // Rotate moves the spiraling circle around the canvas in a large orbit.
  var time = new Date();
  context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
  
  // Translate determines the location of the small circle.
  context.translate(50, 0);  
  
  // Rotate causes the circle to spiral as it circles around the canvas.
  context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
  
  // determines the size of the loop
  context.translate(0, 5);  
  
  // This draws the circle
  context.beginPath();
  context.arc(5, 5, 4, 0, Math.PI*2, true); 
  context.stroke();
  
  // Restores the canvas to the previous state
  context.restore();
  window.requestAnimationFrame(draw);
}  // draw

This is an example of a Cascading Style Sheets (CSS) that creates a black border around a canvas element.

/* style the canvas element with a black border. */
canvas { border: 1px solid black; }

This HTML file creates a canvas element and uses external JavaScript and CSS files.

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="myJavascript.js"></script>
        <link Rel="stylesheet" Href="myStyle.css" Type="text/css">
    </head>
    <body>
        <canvas id="canvas" width="160" height="160" />
    </body>
</html>

Quickstart: Drawing to a canvas