Wednesday, August 25th, 2010
Real World Canvas Tips from Hakim El Hattab
Category: Canvas
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.
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.
Posted by Brad Neuberg at 5:00 am
12 Comments





Concerning cross browser implementation and compositing: last time I checked some of the compositing modes are broken in WebKit-based browsers.
“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.
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).
“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.
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).
undocumented features == innovation != standards
Those experiments are great!
@edwinm, Documented features didn’t really fare much better when Microsoft was fighting standards.
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
About the clearRect vs setting width/height, which is faster of the two?
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.
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!