Categories: Blog

Canvas Animations in HTML5

HTML5’s Canvas and CanvasRenderingContext2d bring something to HTML5 that has long been missing from HTML: the ability to draw pixels into a browser window. I wrote about the canvas API in a previous post entitled Making HTML5 Come Alive with the Canvas API. This time, I’d like to build on that post by exploring a subject for which HTML5 provides no native support: canvas animations.

Silverlight has a robust animation engine built in that makes it easy to make objects move around the screen. HTML5 does not, but you can use timer functions to move objects around by repositioning them at regular intervals. Because HTML5’s canvas API is an immediate-mode drawing API (as opposed to Silverlight’s retained-mode API), moving an object from one position to another requires you to erase it from its current position before drawing it in its new position. Erase, draw, repeat – that’s the basic technique for animating movement within a canvas in HTML5. But as you’ll see, it’s possible to animate CSS properties of the canvas itself to lend the whole affair a retained-mode feel.

For a demonstration, point an HTML5 browser such as Internet Explorer 9, Firefox 4, Chrome 10, Opera 11, or Safari 5 to https://training.atmosera.com/html5/MovingAnimation1.html. You’ll see a page containing a red ball that measures 100 pixels in diameter bouncing around in a 400×400 canvas:

Here’s the code that animates the red ball. Every 10 milliseconds or so, the move function erases the ball by calling CanvasRenderingContext2d’s clearRect method. Then it computes the ball’s new position and draws a red circle there. Like frames in a video, it creates the illusion of motion:

 

// Set a timer to fire every 10 milliseconds

setInterval("move()", 10);

 

function move() {

    // Erase the circle from its old position

    _dc.clearRect(_x – 50, _y – 50, 100, 100);

 

    // Compute the circle’s new position

    var x = _x + _dx;

 

    if (x < 51 || x > (_cx – 51)) {

        x = _x – _dx;

        _dx = -_dx;

    }

 

    var y = _y + _dy;

 

    if (y < 51 || y > (_cy – 51)) {

        y = _y – _dy;

        _dy = -_dy;

    }

 

    _x = x;

    _y = y;

 

    // Redraw the circle in its new position

    _dc.fillStyle = "red";

    _dc.beginPath();

    _dc.arc(_x, _y, 50, 0, Math.PI * 2, true);

    _dc.fill();

}

 

Nothing hard about that. And one of the nice things about clearRect is that works equally well against complex backgrounds. To see what I mean, check out the page at https://training.atmosera.com/html5/MovingAnimation2.html. Unlike its predecessor, it animates a ball against a background consisting of a wood-grain image. For good measure, it also uses a radial gradient fill to make the ball look a little more realistic:

While there’s nothing inherently wrong with animating an object this way, developers used to retained-mode graphics subsystems will come away feeling a little cold. Wouldn’t it be nice if there were a way draw the ball once and then move it around the screen without having to continually erase and redraw it? Funny you should ask. Because with a little help from CSS, you can do just that.

The third example in this series – https://training.atmosera.com/html5/MovingAnimation3.html – does things a little differently. It looks the same on the outside, but on the inside, instead of erasing and redrawing a ball in a 400×400 canvas, it draws the ball once in a 100×100 canvas. Then it uses a timer function to animate the canvas’s CSS left and top properties. Now the browser takes care of doing the erasing and redrawing. Here’s the modified move function:

 

function move() {

    // Get the ball’s current position

    var left = _canvas.style.left;

    var top = _canvas.style.top;

 

    var x = parseInt(left.substring(0, left.length – 2));

    var y = parseInt(top.substring(0, top.length – 2));

 

    // Compute the ball’s new position

    x += _dx;

 

    if (x < 0 || x > (_cx – 101)) {

        _dx = -_dx;

        x += (2 * _dx);

    }

 

    y += _dy;

 

    if (y < 0 || y > (_cy – 101)) {

        _dy = -_dy;

        y += (2 * _dy);

    }

 

    // Move the ball to its new position

    _canvas.style.left = x + "px";

    _canvas.style.top = y + "px";

}

 

Animating the canvas position rather than animating the position of something within the canvas is a huge step in the right direction. And it has the added advantage that it allows the browser to use the GPU to move pixels around the screen – something the browser cannot do when your code is continually erasing and redrawing. Keep this in mind when building animations in HTML5.

Jeff Prosise

Recent Posts

8-Step AWS to Microsoft Azure Migration Strategy

Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…

1 day ago

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

1 week ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

2 months ago