Posted on by & filed under Content - Highlights and Reviews, Web Development.

HTML5’s canvas is a very powerful rendering tool, but at its heart, it is still just another block-level DOM element as far as the web browser’s layout engine is concerned.

Although the <canvas> tag accepts a grand total of two attributes (width and height), it can be styled according to a vast number of CSS properties. We can take advantage of this fact to apply CSS styling to make the browser work for us, improving performance and adding interesting effects.

Upscaling

The degree of heavy lifting done by the GPU will ultimately come down to the number of pixels we need to push on any given frame. Therefore, it is no surpise that rendering performance is highly dependant on the resolution of your canvas.

Fortunately, using CSS, we can reduce the resolution of the canvas while presenting a larger viewport dimension to the user.

For this example, I am using an adaption of a classic processing.org experiment, the Metaball demo, described as “organic-looking n-dimensional objects”. A runnable version of the Metaball demo can be found here: http://moot-point.com/demos/metaball/metaball.html.

The Metaball demo ends up being a rather intensive process since we are using canvas’ getImageData() and putImageData() functions to perform color blending operations at the pixel level. This is especially pronounced at higher resolutions.

On our first run of the demo, we’ll create a 300 x 300 canvas as follows:

When running the Metaball demo against the larger canvas, the experience is rather choppy — as you can see here, I am getting a total of about 15 fps using Chrome 18.

To measure framerates, I am using Mr. Doob’s Javascript Performance Monitor, which is available at https://github.com/mrdoob/stats.js.

Next, in an effort to improve performance, we will reduce the dimensions of the canvas to 150 x 150:

Running the same Metaball demo against the smaller canvas, our framerate leaps to over 50 fps. The resulting effect is fast, fluid motion. The tradeoff here is that the area of the viewport has also been cut significantly.

Here is where CSS comes to the rescue! We can retain the fast-performing 150 x 150 canvas resolution, but instruct the browser to display the viewport at the original size of 300 x 300 using the height and width CSS properties. This can be done as follows:

The outcome is the appearance of a larger viewport with the performance the smaller resolution.

Anti-aliasing

The upscaling effect described above certainly does not come without a cost, as pixelation will occur as the canvas is scaled up by the browser (not unlike images in an <img> tag).

All major browsers will perform a certain degree of anti-aliasing as the image is scaled up. The level of anti-aliasing is dependent on browser implementation of the canvas spec and cannot be controlled.

While the effect is not immediately perceptible with certain graphical effects such as the metaball demo, it can be noticeable in more detailed applications, such as the following example. On the left is the actual baseline image, on the right is the result of rendering the image to the canvas at a smaller size, and then scaling up to 300 x 300. In the end, it is an exercise to find the best compromise between performance and quality.

Scaled up from 50 x 50:

Scaled up from 150 x 150:

Scaled up from 250 x 250:

Preserving data

Other than performance gains, there is another advantage of using CSS to set the size of the canvas viewport. The canvas dimensions can be adjusted on-the-fly without losing any image data.

This is in contrast to programmatically modifying the width or height attributes of a canvas — in that case, all image data that had been previously written to the canvas would be cleared out. However, setting the CSS width/height does not exhibit the same issue — image data is preserved, while the browser simply scales the viewport.

Background images

When a game calls for a background image, our first instinct might be to use canvas’ drawImage() command to draw a background image, as follows:

Below is the result. The examples make use of a very large 3000 x 3000 background image — although such a large background size is admittedly a bit contrived, the exaggeration allows us to more easily see measurable improvements. The character shown here rendered on top of the background image utilizes an alpha channel to achieve transparency.

With framerates of ~40 fps, it is clear redrawing a background image on every frame in this way can be expensive.

An alternative to rendering the background in this manner is to utilize CSS. We can set a CSS background image for the canvas element as follows:

As seen by the increase in framerate to ~60 fps, CSS backgrounds clearly have the potential to improve framerates quite a bit. If the background is of a smaller size, the performance advantage will lessen. However, more often than not, the CSS background image will outperform the canvas background.

Also, the transparency in the foreground character continues to reveal the background image behind as you would expect.

One important caveat is that the performance gain by using CSS backgrounds can only be achieved when utilizing static, unmoving backgrounds. If we call upon the background to animate using a horizontal scroll, for example, it will require us to animate the CSS background-position-x property. CSS animation is ultimately the kiss of death when it comes to high-performance apps, in an overwhelming amount of cases it will be much more performant to draw and animate the background using the canvas drawImage() rather than animating the CSS properties of a background image.

An added bonus of using a CSS background image is that one can make use of additional CSS background properties, such as background-repeat, background-position and background-attachment. With these properties, it is possible to easily manipulate the background with little added rendering cost.

3D

3D is often thought of as a realm unique to webGL, which has the potential to open up a world of possibilities. Sadly, at time of this writing, several browsers provide no support for webGL, such as Internet Explorer and the Android browser. Additionally, the entry level to webGL development is high compared with the 2D canvas API.

On the flip side, if we restrict ourselves to the 2D canvas context, creating 3D effects using software emulation is not a trivial manner in terms of implementation or performance.

Thankfully, we have access to a full suite of 2D and 3D transformations with CSS out-of-the-box and ready to use. The good news is that support for 3D CSS transforms is almost ubiquitous — Internet Explorer 10 and Android browser 3.0 include full support for 3D CSS transforms.

The image above is a result of a 45 degree rotation in the y direction in 3D space. Notice that even though we have applied a 3D transform, the framerate has not been adversely affected when compared with the non-transformed version ran earlier.

The effect is achieved via the following CSS:

Simple enough! But this is not the reality of the current-day browser alphabet soup. To ensure cross-platform support, it would actually be necessary to define all of the following vendor-specific CSS properties:

While only one set of transformations can be applied to a single canvas element (rotation, translation and scale), more interesting effects can potentially be achieved by layering multiple canvas elements and applying different 3D transformations to each. Such effects could be as mundane as a bit of incidental background scenery, or incorporated as a novel gameplay mechanic.

This should help you when creating games with HTML5 Canvas.

Safari Books Online has the content you need

Check out these HTML5 Canvas books available from Safari Books Online:

You’ll learn how to build interactive multimedia applications with HTML5 Canvas, using this new element to draw, animate, compose images, and more. You’ll also learn the best way to use existing JavaScript libraries, as well as how to incorporate related aspects such as audio and video.
Foundation HTML5 Canvas: For Games and Entertainment teaches you how to make exciting interactive games and applications using HTML5 canvas. Canvas lets you produce graphics, animations, and applications using the HTML5 and JavaScript web standards. It allows you to draw directly within the browser without the need for third-party plugins like Adobe Flash, and so canvas works perfectly across desktop and mobile devices, like the iPhone and Android.
HTML5 Games Development by Example will show you how to use latest HTML5 and CSS3 web standards to build card games, drawing games, physics games and even multiplayer games over the network. With the book you will build 6 example games with clear step-by-step tutorials.
HTML5 Canvas Cookbook begins by covering the basics of the HTML5 Canvas API and then provides techniques for handling features not directly supported by the API such as animations and canvas interactivity. It winds up by providing detailed templates for a few of the most common HTML5 canvas application.
Core HTML5 Canvas: Graphics, Animation, and Game Development presents a code-fueled, no-nonsense deep dive into that API, covering everything you need to know to implement rich and consistent web applications that run on a wide variety of operating systems and devices.
If you’re a web developer looking to use this new version of HTML, you might be wondering how much has really changed. Head First HTML5 Programming introduces the key features — including improved text elements, audio and video tags, geolocation, and the Canvas drawing surface — and uses concrete examples and exercises to apply and reinforce these concepts.

About this author

Kevin Moot has had an interest in computer graphics since creating games as a wee lad on his Apple IIe – complete with its vast array of six colors and a mind boggling 280×192 resolution. Kevin has worked with HTML5’s canvas technology for several cutting-edge websites and counts HTML/CSS, JavaScript and .NET among his specialties. He currently works at The Nerdery as an interactive software developer.

Tags: Canvas, CSS, Games, html5, Javascript,

Trackbacks/Pingbacks

  1.  HTML5 Canvas Games: Tracking Transformation Matrices | Safari Books Online's Official Blog