The HTML 5 Canvas - Good Clean Fun
Posted by Tom on 2009-08-11 20:25
So the plan was it open this weblog with a deep and illuminating post. Something .NETty and architectural in nature. But then I got distracted by shiny things and so instead I bring you something completely different: silly baubles.
<canvas id="MainCanvas" width="300" height="300" />
But of course the fun really starts outside the markup, where the wild things are.
var context = canvas.getContext('2d');
The canvas object is the access to the canvas element in the DOM, and does little else beyond exposing the attributes of the canvas tag. The fun really starts when you get your grubby little mits on the context. You get some simple vector drawing functions, allowing you to draw lines, rectangles, arcs, and bezier curves if you're nasty, along with a series of fill options such as gradient and patterns. I'll not go into the details because I can't be bothered and you can just look it up here. Time for shinys!
Balls . . . heh heh
I love particle systems to an almost unhealthy degree so here's a load of bouncing balls. I was going to make this a lot more involved in terms of using the features of canvas, but then I got distracted by mechanics and took a sharp left at the junction of Newton and Collision Response and ended up in the bad side of town where the physicists hang out. Dang.
So yeah, not a lot to be said for this one. It's mostly badly faked collision model and you could actually do this in non-canvas, venerable DHTML really easily. This one is mostly an exercise in how to set up the animation using setInterval and the like.
The only real thing of some note in here is some cheap motion blur. Rather than clear the frame every time I'm simply drawing over the entire canvas with a rectangle that's the same colour as the background but with a low alpha (or opacity, if that terminology seems more familiar to you.) This will work fine unless you're using the draw order to depth-cue your objects (if you need an object to look like it's 'behind' another by drawing the further object before the nearer one).
This second one is a lot more feature-filled, since it touches on transformations and the transformation stack and patterns and multiple canvas and alpha blending and stuff.
First the blocky image is drawn into a canvas, and a pattern is created from it. This can then be passed into the fillStyle property of the context and will be tiled across any filled object you want to render. In this case a BIG DAMN SQUARE, because I'm interesting like that.
Also on this one you can see an example of transformations. The transformation are cumulative and non-associative - so a rotation of X followed by a translation of Y is not the same as a translation of Y followed by a rotation of X. A transformation stack is available and the concept will be familiar to anyone whose has used a graphics API in the past. If you can't see a use for one then I wouldn't sweat it at the moment. Suffice to say that the stack allows you to save the current set of transformations, and retrieve them again to roll the transformation back to a previous state.
It's a valid question.
But there could well be more - the astute among you will have noticed that we're passing an argument to the getContext call. The fact that you have to ask for '2d' now implies that '3d' may be available later. It's not part of the spec, but that hasn't stopped people running with it. Firefox currently has an extension that ties to OpenGL ES 2.0 (shaders and everything!) and Opera has included their own take on the 3D canvas natively. Could well be an interesting time for browser games in the next couple of years.