I’ve been experimenting with the <canvas> tag the last few days and from what I’ve seen, it’s got potential but it’s got a ways to go before we’re replacing Flash with it. But, in order to learn how to use it, I’ve been trying to reproduce things I can remember making when I was first learning Flash and ActionScript, and one of those things was a bouncing ball who’s movements where controlled through code.
To start off, here’s the HTML:
1
| <canvas id="canvas" width="400" height="300"></canvas> |
You have to assign the height and width of the <canvas> tag in the HTML because the default height is 150 pixels and the width is 300 and if you set the dimensions with CSS, the dimensions of the content inside the <canvas> will skew to the ratio of the CSS dimensions. For example, if you set the width to 600 pixels in the CSS and make a rectangle that’s 100 pixels wide, it will display at 200 pixels wide because you’ve double the width of the <canvas> with CSS. We also need to give the <canvas> an id of “canvas” so we can reference it with our JavaScript.
So for CSS, all I’ve included is this:
1 2 3
| #canvas {
border:1px dashed black;
} |
It’s just there so that I can see the edges of the <canvas>.
JavaScript is what powers the <canvas> and to make this work, it takes about 35 lines of JS, not that much.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| var canvasWidth = 400,
canvasHeight = 300,
ball_x = 5,
ball_y = 44,
ball_dx = 5,
ball_dy = 5;
function init() {
var canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
setInterval('draw();', 25);
}
function clearCanvas() {
context.clearRect(0,0,canvasWidth,canvasHeight);
}
function ball(x,y,r) {
context.fillStyle = '#f00';
context.beginPath();
context.arc(x,y,r,0, Math.PI * 2, true);
context.fill();
}
function draw() {
clearCanvas();
ball(ball_x, ball_y, 10);
if (ball_x + ball_dx > canvasWidth || ball_x + ball_dx < 0) {
ball_dx = -ball_dx;
}
if (ball_y + ball_dy > canvasHeight || ball_y + ball_dy < 0) {
ball_dy = -ball_dy;
}
ball_x += ball_dx;
ball_y += ball_dy;
} |
So what are we doing here? Well, the first thing we do is define our variables:
1 2 3 4 5 6
| var canvasWidth = 400,
canvasHeight = 300,
ball_x = 5,
ball_y = 44,
ball_dx = 5,
ball_dy = 5; |
Ball_x and ball_y are our ball’s initial position and ball_dx and ball_dy are the speed our ball will be travelling.
1 2 3 4 5 6
| function init() {
var canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
setInterval('draw();', 25);
} |
In our init() function, we use the getElementById to find our <canvas> and then we set the context to 2D because right now that’s all you can do, although, one day we’re supposed to be able to set the <canvas> to 3D. Next, setInterval is what we use to actually make the animation fire. It will called the function draw() and it will fire every 24 milliseconds.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function draw() {
clearCanvas();
ball(ball_x, ball_y, 10);
if (ball_x + ball_dx > canvasWidth || ball_x + ball_dx < 0) {
ball_dx = -ball_dx;
}
if (ball_y + ball_dy > canvasHeight || ball_y + ball_dy < 0) {
ball_dy = -ball_dy;
}
ball_x += ball_dx;
ball_y += ball_dy;
} |
What we’re doing in the draw() function is redrawing the ball every time the function is fired. In the if statements, we see if the ball has reached the edge of the <canvas> and if it has, we reverse it’s direction. To redraw the ball, we call the ball() function by passing in 3 values, the ball’s x and y positions and the ball’s radius.
1 2 3 4 5 6
| function ball(x,y,r) {
context.fillStyle = '#f00';
context.beginPath();
context.arc(x,y,r,0, Math.PI * 2, true);
context.fill();
} |
So when we pass in the new values, the ball() function will redraw the ball in it’s new position. The fillStyle sets the color to red and arc() sets the position, the radius, the starting point, Math.PI * 2 sets the arc to a full circle and then true or false sets clockwise or counter-clockwise.
In the draw() function, you might have noticed a function called clearCanvas() being called. One of the big differences between the <canvas> and the stage for Flash is that the <canvas> is actually redrawing itself every time the setInterval fires and it won’t remove the old ball position. So, in order to get the effect we’re looking for, we need to clear the <canvas> every time the ball moves.
1 2 3
| function clearCanvas() {
context.clearRect(0,0,canvasWidth,canvasHeight);
} |
To do this, we call the clearRect() function where we set the position to 0,0 and set the width and height to width and height of the <canvas>. This way, we will clear the <canvas> every time we redraw the ball which will make it look like the ball is bouncing around. If we don’t do this, then the ball won’t be removed and eventually the entire <canvas> will fill up.
Finally to make the JavaScript run, we need to add this to the body tag:
Now, after the page loads, it will run the init() function. You can also attact this to a button or a link if you want to start the animation that way.
Check out the demo.
So far, all the most complicated <canvas> examples I’ve seen have been done by hardcore programmers and are too complex to be something that people can realistically build for clients or even for fun. I think for <canvas> to really take off someone like Adobe is going to need to come out with an IDE that will do most of the heavy lifting for us. But for now, we can get started with things like this.