kirupa.com - Animations and the HTML5 Canvas 


Active Discussions

Animations and the HTML5 Canvas

by kirupa   |   1 July 2011

  Have questions? Discuss this HTML tutorial with others on the forums.

You probably already know that the Canvas is basically a giant surface where you can draw into. By drawing and re-drawing very quickly, that same surface can be used for creating animations.

The below video showcases an example of me animating a circle's size in and out:

[ click here for a live / running example ]

If running code is more of your thing than a video, you can also check out a live example if your browser supports HTML5 and the Canvas tag. In this article, let’s look at the concepts and the code needed to be able to create animations on a canvas similar to the example you see above.

Getting Started
Let’s first start with the code that just gets a circle drawn and displayed inside our canvas. We’ll look at animating the size of that circle later.

Inside a blank HTML document, copy and paste everything you see below:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Circle Example</title>
 
<style>
 
#myCanvas
{
border-width: 1px;
border-style: dotted;
border-color: Gray;
}
 
</style>
 
</head>
 
<body>
<div id="container">
<canvas id="myCanvas" width="400" height="250">
 
</canvas>
</div>
 
<script>
 
var mainCanvas = document.getElementById("myCanvas");
var mainContext = mainCanvas.getContext('2d');
 
function drawCircle() {
mainContext.clearRect(0, 0, 400, 250);
mainContext.beginPath();
mainContext.arc(200, 125, 50, 0, Math.PI * 2, false);
mainContext.closePath();
mainContext.fillStyle = "#006699";
mainContext.fill();
}
drawCircle();
 
</script>
</body>
 
</html>

When you preview this in your browser, you will see a solid blue circle displayed in the center of your canvas:

you will see a single blue circle

This is a good starting point. What we want to do next is scale the size of the circle up and down, but before we get to that, let's just take a step back and look at how animating inside a canvas will even work.

How Animation on the Canvas Works
The Canvas object is very basic and doesn’t hold your hand when you want to do things that you may have been able to do easier in other technologies and platforms. You may have gotten a feel for that when you had to write JavaScript (that’s code!) to draw something as simple as a circle. Making your visuals move, though, isn't particularly difficult once you have a way of drawing what you want to animate.

The way you animate is by drawing individual frames and then playing them in sequence very quickly. Each frame would be ever-so-slightly different than the previous frame, and when these frames are played fast enough, the differences coalesce to show motion. For example, here is an example of the individual frames that make up a circle sliding to the right, fading in, and growing larger at the same time:

grid of frames

If we were play them together really quickly in 1 second, you would see an animation that would look something like this:

onion_skin_animation

If you cleared what you saw between each frame, you'll see an animation of your circle morphing and changing when the frame are played through reasonably quickly. Let's more precisely describe the steps involved:

  1. Draw the first frame of your animation.

  2. Clear your canvas.

  3. Draw the second frame of your animation.

  4. Clear your canvas.

  5. Draw the third frame of your animation.

  6. ....and so on!

That doesn't seem very hard at all. As you will see shortly, adding the code to create a simple animation isn't very hard either.

Modifying the Code
Based on the simple formula we have, what we are going to do is write some code that rapidly redraws our canvas with a new version of our circle. First, let's add a counter variable to our code:

<script>
 
var mainCanvas = document.getElementById("myCanvas");
var mainContext = mainCanvas.getContext('2d');
var counter = 0;
 
function drawCircle() {
mainContext.clearRect(0, 0, 400, 250);
 
mainContext.beginPath();
mainContext.arc(200, 125, 50, 0, Math.PI * 2, false);
mainContext.closePath();
mainContext.fillStyle = "#006699";
mainContext.fill();
}
 
drawCircle();
 
</script>

This variable is used as an incrementer that helps our circle's size increase or decrease. It will make more sene when you see it used in a few seconds.

The next thing we are going to do is modify our drawCircle function to take our counter variable so that the size of the circle is dependent on it:

<script>
 
var mainCanvas = document.getElementById("myCanvas");
var mainContext = mainCanvas.getContext('2d');
var counter = 0;
 
function drawCircle() {
 
mainContext.clearRect(0, 0, 400, 250);
 
mainContext.beginPath();
mainContext.arc(200, 125, 25+150*Math.abs(Math.cos(counter/25)), 0, Math.PI * 2, false);
mainContext.closePath();
 
mainContext.fillStyle = "#006699";
mainContext.fill();
 
counter++;
}
 
drawCircle();
 
</script>

To dive into this a bit further, the first (and probably the biggest) change was to make our circle's size not be a fixed value but be a trignonometric function whose output varied from 0 and 1 depending on what the value of the counter variable was:

25+150*Math.abs(Math.cos(counter/25))

This means our circle's size will either be 25+0 at the small extreme or 25+150 at the large extreme. This ability to stay within this narrow range, even if the value of the counter variable is increasing, gives our circle's size the wobbling effect that you see.

The last change we do to this function is increment our counter variable:

counter++;

Everytime our circle is drawn, the counter variable that determines its size will be incremented by 1. This means the next time the circle is drawn, it will be drawn at a slightly different size than the one drawn earlier.

When you are constantly drawing something into your canvas, how do you prevent what you are drawing from overlaying and constantly modifying the original image? Very simple - you clear the canvas before you draw the slightly updated version of the circle.

 Clearing your canvas is handled by the very first line in our drawCircle function:

mainContext.clearRect(0, 0, 400, 250);

The clearRect method on our context object allows you to specify the rectangular bounds of the canvas region you wish to clear or invalidate. Because our canvas is 400 pixels wide and 250 pixels tall, the rectangular coordinates we specified are for clearing the full area.

If you do nothing else and preview what you've done so far in your browser, here is what you will see:

blue circle at the initial frame

This is the end result of your drawCircle call that drew the first frame of your animation where the size of the circle corresponds to your counter variable being 0. Wohooo...sort of!

The last thing we are going to do is setup a way to call drawCircle rapidly to create the animation we want. This is accomplished by using the setInterval function.

Go ahead and add the following setInterval function to your code above the drawCircle function declaration:

<script>
 
var mainCanvas = document.getElementById("myCanvas");
var mainContext = mainCanvas.getContext('2d');
var counter = 0;
 
setInterval(drawCircle, 1000/30);
 
function drawCircle() {
 
mainContext.clearRect(0, 0, 400, 250);
mainContext.beginPath();
mainContext.arc(200, 125, 25+150*Math.abs(Math.cos(counter/25)), 0, Math.PI * 2, false);
mainContext.closePath();
 
mainContext.fillStyle = "#006699";
mainContext.fill();
 
counter++;
}
 
drawCircle();
 
</script>

The setInterval function takes two arguments - the function to call and a number describing the number of milliseconds to wait before calling the same function again:

setInterval(drawCircle, 1000/30);

In our case, what we are doing is telling JavaScript to call the drawCircle function at a rate of 1000/30 times a second. This means every 33.3333 milliseconds, the drawCircle function gets called.

Because the counter variable gets updated (leading to our circle's size being different) and our entire scene is redrawn with each call to drawCircle, you have a code-based solution to the "playing back images really quickly to simulate animation" that you saw at the beginning.

Conclusion
So, as you can see, drawing your shape is the hard part. Actually getting what you've drawn to move around isn't particularly difficult once you know which parameters to alter. The example you have seen here is pretty simple that involved just a single item moving around. When moving many items, your code becomes a little bit more complex if you wish to keep track of the various things being drawn. You can check out the Animating Many Things on a Canvas tutorial to learn more.

Need Help?

If you have questions, need some assistance on this topic, or just want to chat - please drop by our friendly forums and post your question. There are a lot of knowledgeable and witty people who would be happy to help you out. Plus, we have a large collection of smileys you can use

Share

Did you enjoy reading this and found it useful? If so, please share it with your friends:

If you didn't like it, I always like to hear how I can do better next time. Please feel free to contact me directly at kirupa[at]kirupa.com.

Cheers!

Kirupa Chinnathambi
about | facebook | twitter


cloud storage
                          EdgeCast CDN
kirupa.com's fast and reliable hosting provided by Media Temple. Creative web apps. Make your own free flash banners and photo slideshows.
HTML5 CSS3 Mobile Gallery for iPhone, iPad Flash effects. Art without coding.
Flipping Book - page flip flash component. Flash-Gallery.com - Get your flash photo gallery (flash component or swf gallery
Learn how to advertise on kirupa.com