[This is part 5 of an ongoing series of posts examining the HTML5 Canvas element. In Part 1 of this series, I introduced Canvas and prepared a template to make further explorations a bit simpler, and also introduced JsFiddle, a neat tool for experimenting with and sharing web code. In Part 2, I demonstrated the ability of Canvas to allow your page background to shine through, and showed you how to render simple shapes on the drawing surface. In Part 3, I showed how to draw paths and text in Canvas. In Part 4, I showed how to transform the drawing context and scale, rotate, and skew your drawings.]
Get Moving
Simply defined, animation is a technique that provides the illusion of movement by changing the position, size, shape, or other properties of a drawn object over time. In traditional animation, artists draw a scene one frame (or cel) at a time, by hand, changing each scene just slightly with each new frame. Thankfully, we don’t have to go through such a laborious process to create animations with HTML5 Canvas.
So far in this series, we have only drawn shapes on our canvas once. In order to start using animation, we need a way to draw multiple frames, and at a rate that provides the necessary illusion of smooth movement. But first, let’s draw a single frame of content, and we’ll keep it nice and simple…we’ll use the same reference grid as in previous examples, and we’ll add a small white box to our canvas, using the following code (if you’re new to the series, see Part 1 for the page template we’re plugging this code into, or the jsFiddle below for the complete finished example):
1: $(document).ready(function() {
2: var canvas = $("#myCanvas").get(0);
3: var context = canvas.getContext("2d");
4: var posX = 0;
5: var posY = 75;
6:
7: function renderGrid(gridPixelSize, color)
8: {
9: // grid code omitted for brevity
10: }
11:
12: function renderContent()
13: {
14: context.save();
15: renderGrid(20, "red")
16: context.beginPath();
17: context.fillStyle = "White";
18: context.strokeStyle = "White";
19: context.fillRect(posX, posY, 10, 10);
20: context.restore();
21: }
22:
23: renderContent();
24: });
In the code above, we’re using jQuery‘s ready event to draw our reference grid and a small white rectangle on the canvas. I’ve also added a couple of variables (in bold) to hold the current position of the rectangle. Here’s what our example looks like so far:
OK, so it’s a bit plain perhaps, but we can make it better with animation. To get started, as noted earlier, we need a way to draw multiple frames at a specific rate, and for that purpose, most folks use what’s called an animation or game loop, which looks something like this:
1: function animationLoop()
2: {
3: canvas.width = canvas.width;
4: renderContent();
5: posX += 5;
6: if (posX > 500)
7: posX = 0;
8: setTimeout(animationLoop, 33);
9: }
In the code above, I’ve created a function that will take care of drawing a frame of our animation each time its called. Recall from earlier parts of the series that setting canvas.width will reset the canvas. The rest of the code simply draws our content, then adds 5 to the posX variable which determines where our box is drawn, and if posX is larger than 500, resets it to 0. The last line is key…we use JavaScript’s setTimeout function to automatically call animationLoop every 33 milliseconds, which gives us a frame rate of approximately 30 frames per second (to get FPS, just take 1000ms and divide by the target frame rate – 1000 / 30 = 33.3333333333333). Here’s what it looks like:
Note: If you can’t play the video, you can also see the code in action by clicking the Result button below…
Here’s a jsFiddle for the above example:
As you can see, it’s pretty easy to get things moving in JavaScript and Canvas. Of course, moving a little white box is just the start. Let’s go back to our pal from the previous entry in this series, and have a little more fun. We’ll add a few fields to keep track of some additional properties of the object we’re drawing (note that for more complex cases, it probably makes sense to look at creating objects to encapsulate all of the relevant properties for a given shape that you’re drawing), as well as a new function to aid in drawing our shape (new/modified code is in bold):
1: $(document).ready(function() {
2: var canvas = $("#myCanvas").get(0);
3: var context = canvas.getContext("2d");
4: var startAngle = 0.25;
5: var endAngle = 1.75;
6: var gapClosing = true;
7: var posX = 0;
8: var posY = 75;
9:
10: function renderGrid(gridPixelSize, color) {
11: // omitted
12: }
13:
14: function setAngles() {
15: if (startAngle <= 0) gapClosing = true;
16: else if (startAngle > 0.25) gapClosing = false;
17:
18: if (gapClosing) {
19: startAngle = startAngle + 0.05;
20: endAngle = endAngle - 0.05;
21: }
22: else {
23: startAngle = startAngle - 0.05;
24: endAngle = endAngle + 0.05;
25: }
26: }
27:
28: function renderContent() {
29: context.save();
30: renderGrid(20, "red")
31: context.beginPath();
32: context.fillStyle = "Yellow";
33: context.strokeStyle = "Yellow";
34: context.arc(posX, posY, 50, startAngle * Math.PI, endAngle * Math.PI);
35: context.lineTo(posX, posY);
36: context.stroke();
37: context.fill();
38: context.restore();
39: }
40:
41: function animationLoop() {
42: canvas.width = canvas.width;
43: renderContent();
44: setAngles();
45: posX += 5;
46: if (posX > 500)
47: posX = 0;
48: setTimeout(animationLoop, 33);
49: }
50:
51: animationLoop();
52: });
If everything’s working as expected, here’s what it should look like:
Note: If you can’t play the video, you can also see the code in action by clicking the Result button below…
Here’s a JsFiddle with the final code from this post, if you want to play with the APIs:
Summary
Animation in HTML5 Canvas is pretty easy and straightforward to accomplish. Of course, there’s much more you can do, including abstracting some of the animation tasks so you’re not doing quite so much low-level drawing, or even taking advantage of 3rd party libraries to simplify your life.
If you found this useful, why not tell your friends? You can also subscribe to my RSS feed, and follow me on twitter for more frequent updates.
More parts in the series:
- Part 1 – Introduction
- Part 2 – Basic Shapes
- Part 3 – Paths and Text
- Part 4 – Transformations
- Part 5 – Basic Animation (this post) Up next, I’ll show you some more advanced animation techniques…don’t miss it!
- Part 4 – Transformations
- Part 3 – Paths and Text
- Part 2 – Basic Shapes
Comments
Comment by simonsarris on 2012-04-30 15:28:00 +0000
Good series. Always glad to see more good Canvas tutorials.
(And I’m glad to see Microsoft take Canvas seriously, too).
-Simon
Comment by gosukiwi on 2012-04-30 15:30:00 +0000
You use internet explorer..
Comment by Larry Serflaten on 2012-04-30 15:56:00 +0000
One suggestion for a later date would be to center a shape wherever the mouse clicks on the canvas. Once we master drawing, and then add input, we have the beginnings of an interactive canvas!
Comment by Greg on 2012-05-01 18:06:00 +0000
Thanks for taking the time to create the canvas tutorial
Comment by devhammer on 2012-05-02 07:14:00 +0000
Thanks for the suggestion…will keep that in mind for future entries!
Comment by devhammer on 2012-05-02 07:19:00 +0000
Indeed. Should be no surprise, given who I work for. 🙂
But you will find that the animation code works in all of the major browsers (I’ve tested on FF, Chrome, Safari, and Opera, in addition to IE).
Comment by devhammer on 2012-05-02 07:21:00 +0000
@1a8a18792ef62ad316bad28eb03e2e0c:disqus My pleasure! There’s more to come so stop by periodically, or subscribe to the feed.
Comment by devhammer on 2012-05-02 07:21:00 +0000
@simonsarris:disqus Thanks! Glad you’re enjoying the series!
Comment by platzh1rsch on 2012-08-23 14:03:00 +0000
Very nice series! Helped me alot.
I’m even thinking of building it up to a fully functional pacman clone (http://pacman.platzh1rsch.ch).
I probably wouldn’t have any clue of canvas if it wasn’t for these tutorials.
Big up!
Comment by devhammer on 2012-08-23 17:57:00 +0000
Glad you found it helpful. And thanks for the shout-out on your blog. Unfortunately, your pacman clone doesn’t seem to work for me. Tried both IE9 and FF14. Have you tested in those browsers?
Comment by platzh1rsch on 2012-08-24 07:32:00 +0000
Maybe I was just fixing a bug since I’m still working on it, it works just fine now in IE9, also FF and Chrome.
I’m always willing to share good tutorials like yours, keep on the good work. With people like you Microsoft will do just fine in the future 😉
Comment by Jim Nussey on 2016-01-25 11:27:16 +0000
Hi, I linked to this site per recommendation of my instructor in a University of Phoenix HTML5 course. Trying to duplicate your code but I cannot get to work. Could you please refer me to a site where I can download the source code for “Part 5: Basic Animation” example for rotating Pacman? Or email a copy of this HTML5 program?
Thanks,
Jim
Comment by G. Andrew on 2016-01-25 11:37:30 +0000
Hi Jim,
Most of the examples in this blog series include a working example using JSFiddle. You should see a box towards the end of the post with tabs labeled “JavaScript”, “HTML”, “CSS”, and “Result”. If you’re not seeing that, something is wrong with the embed.
You can also access the JSFiddle for this post directly at http://jsfiddle.net/devhammer/hS3Ah/1/
Thanks for visiting.