After all the fuzz cause by Steve Jobs objections against Flash and indirect promotion of HTML5 I wanted to see whats possible using HTML5 and the canvas element. After searching a bit online I stumbled upon some interesting articles. One implementation of Quake2 using HTML5, and the implementation of an SWF player using HTML5. This seeded my interest a little more and I wanted to see how easy it is to get something on the screen.

Simple outline of a tree based renderer

As an example project I wanted to create a simple tree graph renderer inspired by the Flash MovieClip hierarchy. The final outcome should become something like this.

// add root shapes
var canvas = new Canvas(c.canvas, c.ctx);
canvas.addShape(new Symbol(50, 25));
canvas.addShape(new Symbol(160, 25));
canvas.addShape(new Symbol(160, 135));
canvas.addShape(new Symbol(50, 135));

The Canvas element should take care of the rendering process and render the symbols. Rendering the complete tree at 20 frames a second will be done using the following code.

canvas.init();
canvas.render();
canvas.run(20);

Shapes

At a minimum our renderer should be able to place shapes onto the screen. The minimal information I want to update through the Tree is the x and y position. They should be able to update their state and be capable of rendering themselves on a context.

The Box as you can see it moving above has been defined as:

function Box(x, y, width, height) {
    // simple element, just renders a strokeRect
    Shape.call(this, x, y);

    this.width = width;
    this.height = height;

    this.draw = function (ctx) {
        ctx.strokeRect(this._x, this._y, this.width, this.height);
    }
}

This setup enables composition of complex shapes using simpler shapes as can be seen below.

function Symbol(x, y) {
    // initialise shape
    Shape.call(this, x, y);

    // compose this shape out of 2 boxes
    this.box = this.addChild( new Box(0,0,100,100) );
    this.innerbox = this.box.addChild(new Box(10,10,80,80));
}

Behaviours

To create animations we have multiple options. One can always supply a function to update x,y,width,heigh or rotation. But many behaviours are standard, and especially with complex behaviours we would like to compose them. So I added the possibility to add behaviours to specific shapes.

function Behaviour() {
    // Basic methods for a behaviour
    // stores shape in shape and original coords
    this.init = function (s) {
        this.shape = s;
        this.original_x = s.x;
        this.original_y = s.y;
    }

    // apply applies the behaviour .. should
    // be implemented ina specific behaviour
    this.apply = function (time) {
    }
}

To test this behaviour I implemented the Wobble as can be seen above:

function BehWobble(duration,amplitude) {
    // BehWobble is a behaviour
    Behaviour.call(this);

    this.wobble = 0;
    this.duration = 1000*duration;
    this.amplitude = amplitude;

    this.apply = function (time) {
        this.shape.x -= this.wobble;
        this.wobble = this.amplitude * Math.sin(toRad(360*((time%this.duration)/this.duration))); 
        this.shape.x += this.wobble;
    }
}

Putting it together

I update the symbol function to add the behaviour to the boxes. And voila the result can be seen above:

function Symbol(x, y) {
    Shape.call(this, x, y);
    this.box = this.addChild( new Box(0,0,100,100) );
    this.innerbox = this.box.addChild(new Box(10,10,80,80));

    // let the innerbox wobble
    this.box.addBehaviour(new BehWobble(4,10));
    this.innerbox.addBehaviour(new BehWobble(2,10));
    this.innerbox.addBehaviour(new BehWobble(1,-10));
}

Conclusion

Just a little abstraction to rendering stuff in the HTML5 canvas element. So far I am pretty happy with it but started looking for some existing frameworks. Landed on processing.js which looks promising.

Code can be read here, Simple engine code, and the wobbling squares are defined here.


Fork me on GitHub