The canvas API
Two posts ago I promised to tell you something more about the HTML5 technology that I use to draw and animate Boids, that is the
<canvas> element. As you have probably guessed, it is basically just an HTML tag - but its possibilities are truly impressive. With the use of a simple
The canvas API itself is not really complicated in terms of the amount of knowledge to grasp. All the methods and properties are nicely put together on the w3schools reference. Yes, I am aware of the controversy behind w3schools and I admit it’s definitely not the ultimate choice for learning but when it comes to getting to know HTML5, especially if you’re fresh to some of its features, it’s a nice start. Having said that, you should definitely check out the MDN documentation for canvas which provides you with in-depth information on all the API’s features.
Basically, the canvas API consists of a set of functions and properties. Functions can be divided as per their purpose like so:
- line and shape functions (for example:
- text functions (
- transform functions (
In addition to the functions, canvas API provides you with a set of properties that are basically designed to let you style the elements before they get drawn on canvas. Some of these properties are:
OK, let’s get down to actual coding so that you can check yourself how to make use of canvas. Once you get the knack of it, I promise, you’ll have fun!
First, let’s insert canvas on our website. In a place of your choice simply put:
No need to say that the above id, width, height and fallback text is up to you. You might be tempted to omit width and height and choose to style those in CSS but don’t do that, it won’t work. You need to define width and height directly inside of the
Now we need to define the context in which we want to work. In most of the cases, you will need a 2D context. The canvas element has a special method for that called
Finally, let’s draw something simple like a rectangle:
fillRect() method takes four parameters:
height. The x and y coordinates define the rectangle’s upper-left corner’s position. The default color is black, that’s why you can see a black rectangle on your canvas now even though you didn’t set any styling. Actually if you do want to style your components anyhow, you should define the visual side first. Let’s add some colour to our rectangle, say, orange for example. Now the code will look like this:
The same way, you can create a rectangle with a stroke, defining its color first:
This will add a blue stroke to your initial rectangle. You might want to alter the stroke’s width - and that’s simple too. The only thing it takes is a
lineWidth method where you define the line’s width in pixels and pass it as a numeric value like so:
Cool, you get the point! The very introduction is behind us, let’s move on to other shapes.
Run rings around the squares!
Time for something slightly more complex: curves. In the case of Boids I initially wanted to represent them as simple circles. To do that, we need the
arc method that lets you draw curves, ovals and circles. As you remember, we need to define styles first. How about some spring colors and stroke of 5px?
Now we need a method to start the path:
…and draw a curve using the canvas
arc method. The
arc method takes 5 obligatory parameters and 1 optional. These are:
- x (the x-coordinate of the center of the circle)
- y (the y-coordinate of the center of the circle)
- r (the radius)
- sAngle (the starting angle, in radians, where 0 is at the 3 o’clock position of the arc’s circle)
- eAngle (the ending angle, in radians)
- counterclockwise (this one is optional and takes a boolean value:
Let’s imagine we’d like the arc to be drawn in the middle of the canvas, with the radius of 20px, taking 90 degrees. Calculating radians may be a bit counterintuitive for you (it is for me!) so why not get ourselves a little helper function that will take degrees and return radians? Like so:
Now let’s move back to our arc and draw it!
A riddle for you: how to draw a circle with fill only, no stroke, as in the case of rough-and-ready Boids. Yeah, I know that you know. :)
Let’s animate it!
Last thing I’m gonna show you is a simple animation that will get you familiarized with some concepts of moving elements around on canvas. Basically, drawing on canvas consists in sequential clearing the canvas and redrawing the element on a new position. In case you perform any transformations on the element while animating it, you will also need to store and restore the canvas. We won’t transfigure our circle anyhow so we can skip these steps.
To schedule the updates you can use one of the following functions:
setInterval(fn, delay) or
requestAnimationFrame(callback). I suggest you go for the third option since it’s best in terms of performance of your animation. Paul Irish explained very nicely the way requestAnimationFrame() method works and why to choose it over
setInterval. The post is old but still valid, just the support of the browser is now almost complete. It’s just Opera Mini that doesn’t understand the deal. Anyways, has anyone of you ever used Opera Mini? Personally, I don’t even know how dude looks like!. ;)
OK, so how to use the
requestAnimationFrame() method? We use it on a global object (that is, in our case, window) and we pass it a callback function which will run each time the browser performs drawing on the screen. So here’s the basic syntax:
Which is, as you know, the same thing as:
With that in mind, let’s write a core for our
animate() function which will run the
requestAnimationFrame() method, calculate next position and then re-draw it.
Next, let’s define the
draw() function. It will be running in a multiple sequence so the first thing you need to do is clear the canvas before re-drawing the element on the next position. To clear the canvas, you need to run the
clearRect() method on the canvas’ context (as you remember, we keep it in a variable called
clearRect() method takes the following parameters:
- x (the x-coordinate of the upper-left corner of the rectangle to clear)
- y (the y-coordinate of the upper-left corner of the rectangle to clear)
- width (of the rectangle to clear, in px: in our case this will be the width of the whole canvas)
Now, the foundation of your
draw() function will look like this:
Having this basis, let’s think of how we will actually deal with moving our element around. For the very beginning, we’ll move the element on x-coordinate only asking it to revert the direction of the movement once the element hits the border of the canvas. We need three variables:
y for initial position and
speed for… yeah, the speed. :)
Let’s declare these at the very beginning, above the
At this moment we can complete the
draw() function and make it draw a circle like we did before in this tutorial:
Finally, we will move the circle on the x-axis by incrementing the
x variable which defines the circle’s horizontal position:
OK, what’s going on here and where do these
360 values come from? As you remember, the canvas width and height are both equal to 400px. The circle’s width is 40px and we start to draw the center of it at
(40, 40) position. This means the circle will hit the left border of canvas at
(40, 40) position and the right border at
(360, 40) (the canvas’ width minus 40px). These two are the moments when we want to revert the direction of the movement.
Let’s have a look at the final code:
At this moment you should see your circle rolling around your canvas from one side to another - and back. Now you can play with the speed, y-axis position and much more. Have fun! :)
I have only touched the very surface of canvas’ possibilities and I’m sure you’ll want much more. Here’s a generous handful of really nice recourses that will help you dive deeper into canvas’ features:
- This is a big one! A selection of top-notch tutorials for any-level coders. Thank you, Code Theory! :)
- A great step-by-step guide by DiveIntoHTML5. As a side note, I encourage you to check out all the DiveIntoHTML5 series, Mark Pilgrim did an excellent job explaining all the HTML5 particularities in a creative yet not overwhelming form.
- A 31-days canvas challenge. Good way to stay on track in the learning process.
How are Boids flying on canvas?
If you’re curious how I’m doing with the Boids, check it out here:
- the source code on GitHub. You can find out how I applied the methods described in the above tutorial to animate Boid instances on canvas. I will be glad to hear your tips on that!
- Boids online
That’s it for now, hope you’ve enjoyed this little playground, see you back soon! :)