Wednesday, August 25th, 2010

Real World Canvas Tips from Hakim El Hattab

Category: Canvas

<p>

From Hakim El Hattab (who has some very nifty HTML5 experiments up) comes some nice tips on using the Canvas tag:

Cross browser implementation

There are no real discrepancies between the canvas outputs of different browsers so long as the JavaScript code is written correctly (if not, browsers tend to try and fix things for you, often resulting in varying results).

Performance

When working with animation on canvas, performance can be a challenge since bitmap operations are very processing expensive, especially at high resolutions. One important optimization rule to follow is to reuse as many pixels as possible between frames. What I mean by that is the fewer pixels that need to be processed each frame, the faster your program will run. A good example of this is when erasing pixels with the clearRect(x,y,w,h)method, it is very beneficial to clear and redraw only the pixels that have changed and not, for instance, a full screen 1920×1280 sized canvas. Unlike the Flash Player’s redraw regions, this management of “dirty rectangles” needs to be done manually for canvas.

State stack & transformation

The canvas can be manipulated via transformations such as rotation and scaling, resulting in a change to the canvas co-ordinate system. This is where it’s important to know about the state stack for which two methods are available: “save” (pushes the current state to the stack) and “restore” (reverts to the previous state). This enables you to apply transformation to a drawing and then restore back to the previous state to make sure the next shape is not affected by any earlier transformation. The states also include properties such as the fill and stroke colors.

Compositing

A very powerful tool at hand when working with canvas is compositing modes which, amongst other things, allow for masking and layering. As an example, you can check out Bakemono, where composite modes are used to mask the eye and mouth. There’s a wide array of available composite modes and they are all set through the canvas context’s “globalCompositeOperation” property.

Anti-aliasing

To allow for sub-pixel drawings, all browser implementations of canvas employ anti-aliasing (although this does not seem to be a requirement in the HTML5 spec). Anti-aliasing can be important to keep in mind if you want to draw crisp lines and notice the result looks blurred. To work around this you will need to either round to integer values or offset by half a pixel depending on if you’re drawing fills or strokes.

Clearing the canvas

To clear the entire canvas of any existing pixels you would normally use the clearRect(x,y,w,h) function but there is another option available. Whenever the width/height of the canvas are set, even if they are set to the value they already have, the canvas is reset. This is good to know when working with a dynamically sized canvas as you will notice drawings disappearing.

[via Mr. Doob]

Cross browser implementation

There are no real discrepancies between the canvas outputs of different browsers so long as the JavaScript code is written correctly (if not, browsers tend to try and fix things for you, often resulting in varying results).

Performance

When working with animation on canvas, performance can be a challenge since bitmap operations are very processing expensive, especially at high resolutions. One important optimization rule to follow is to reuse as many pixels as possible between frames. What I mean by that is the fewer pixels that need to be processed each frame, the faster your program will run. A good example of this is when erasing pixels with the clearRect(x,y,w,h)method, it is very beneficial to clear and redraw only the pixels that have changed and not, for instance, a full screen 1920×1280 sized canvas. Unlike the Flash Player’s redraw regions, this management of “dirty rectangles” needs to be done manually for canvas.

State stack & transformation

The canvas can be manipulated via transformations such as rotation and scaling, resulting in a change to the canvas co-ordinate system. This is where it’s important to know about the state stack for which two methods are available: “save” (pushes the current state to the stack) and “restore” (reverts to the previous state). This enables you to apply transformation to a drawing and then restore back to the previous state to make sure the next shape is not affected by any earlier transformation. The states also include properties such as the fill and stroke colors.

Compositing

A very powerful tool at hand when working with canvas is compositing modes which, amongst other things, allow for masking and layering. As an example, you can check out Bakemono, where composite modes are used to mask the eye and mouth. There’s a wide array of available composite modes and they are all set through the canvas context’s “globalCompositeOperation” property.

Anti-aliasing

To allow for sub-pixel drawings, all browser implementations of canvas employ anti-aliasing (although this does not seem to be a requirement in the HTML5 spec). Anti-aliasing can be important to keep in mind if you want to draw crisp lines and notice the result looks blurred. To work around this you will need to either round to integer values or offset by half a pixel depending on if you’re drawing fills or strokes.

Clearing the canvas

To clear the entire canvas of any existing pixels you would normally use the clearRect(x,y,w,h) function but there is another option available. Whenever the width/height of the canvas are set, even if they are set to the value they already have, the canvas is reset. This is good to know when working with a dynamically sized canvas as you will notice drawings disappearing.

Related Content:

Posted by Brad Neuberg at 5:00 am
12 Comments

++---
2.8 rating from 10 votes

12 Comments »

Comments feed TrackBack URI

Concerning cross browser implementation and compositing: last time I checked some of the compositing modes are broken in WebKit-based browsers.

Comment by stefanw — August 25, 2010

“There are no real discrepancies between the canvas outputs of different browsers so long as the JavaScript code is written correctly”
Hmmm… Well besides Firefox using subpixel antialiasing on text rendering (no other browser currently does this) and not supporting the “darker” globalCompositeOperation option anymore (regression – ARGH!!), they are pretty close.

Comment by rasmusfl0e — August 25, 2010

Just wanted to let you know that the some of the experiments won’t work in Opera 10.61 (it seems to be a mouse event thing).

Comment by philogb — August 25, 2010

“Cross browser implementation”

That’s not really true. I’ve noticed a lot of bugs involved with jamming elements into the iframe and deploying cross-browser to IE6/7 using excanvas.

So if that is your cross-platform bridge library, expect most things to work, but to say that there are no major discrepancies is inaccurate.

Comment by idio — August 25, 2010

Is it documented that the canvas should be cleared if the width and height are set?

If that’s not the case, then it might also be a bug (shared by all browsers) and it might be fixed in some future release.

Unless we’re all going the use this “trick” and the bug can’t be fixed anymore.

Please never use undocumented features as they might stall innovation (as has happened numerous times in the past, just ask Microsoft).

Comment by edwinm — August 25, 2010

undocumented features == innovation != standards

Comment by rasmusfl0e — August 25, 2010

Those experiments are great!

Comment by Jesse — August 25, 2010

@edwinm, Documented features didn’t really fare much better when Microsoft was fighting standards.

Comment by eyelidlessness — August 25, 2010

someone could just check the spec :)

“When the canvas element is created, and subsequently whenever the width and height attributes are set (whether to a new value or to the previous value), the bitmap and any associated contexts must be cleared back to their initial state and reinitialized with the newly specified coordinate space dimensions.”

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#attr-canvas-width

Comment by bckenny — August 25, 2010

About the clearRect vs setting width/height, which is faster of the two?

Comment by Figaro — August 25, 2010

There is a difference between clearRect and setting the width or height. ClearRect does not change any of context properties (colours, transformations etc), setting the width resets all properties to the default.

As far as there are no real discrepancies between the canvas outputs of different browsers. This not true, simply open up http://ie.microsoft.com/testdrive/Graphics/CanvasPad/Default.html and look at the shadow demo.

The worst area of difference is fillText and strokeText on a canvas that has transformations.

Comment by McDaid — August 26, 2010

I think my wording was more explicit than what I had in mind for the cross browser part. Obviously there _are_ differences between browsers. What I was trying to say is that during my experimenting I have not come across any show-stoppers or major problems between the different native browser implementations of canvas (that excludes excanvas).

Thanks for all of the added info on what differences there are, always interesting to learn something new!

Comment by hakim — August 26, 2010

Leave a comment

You must be logged in to post a comment.