startSection('head'); ?> endSection();?> startSection('content');?>

Experiment - HTML5 Canvas Caching

Vector graphics in Canvas can be cpu-intensive, especially with complex designs. Pile on the shapes along with effects such as strokes and gradient fills, and things can get very sluggish.

That's a pity, as vectors are really versatile with a low bandwidth requirement. Luckily, we can mitigate the performance issues somewhat by 'Canvas-caching'. By drawing your vectors once to a hidden Canvas element, and then using this element as a bitmap source, we can give the illusion of complex vector arrangements, but without the performance hit. A single bitmap is a lot quicker to draw than complex vectors. Hover over the image:

*** THIS BROWSER DOES NOT SUPPORT THE CANVAS ELEMENT ***

The simple drawImage command is used with hidden Canvas elements as the source, e.g:

ctx.drawImage( cachedItems[4].canvas, clouds[i].x, clouds[i].y )

Adobe Flash developers have a more formalised version of this technique in their movieclip cacheAsBitmap property.

In the demonstration above, all the vector imagery has been rendered client-side, and cached into a few hidden Canvas elements. The shapes were defined in Adobe illustrator and output as SVG XML. By using the excellent Canvg utility, the SVG definitions are converted client-side into Canvas commands for drawing. This is normally too slow a process for real-time applications like games, but because we are using cached versions, performance is respectable.

This technique would be useful for all sorts cpu-intensive Canvas drawing such as recursive fractal trees, filters or generating 3d sprites. It could be used for a level-of-detail system, whereby items close up are viewed as real vectors that can have parts manipulated in JavaScipt, but the same items in the distance are drawn as a cached Canvas version.

'Hidden' Canvas Elements

These are the actual Canvas elements and their contents. Normally you would just apply display:none to their parent container to hide them.

blog comments powered by Disqus

Please contact me with any questions or comments.

endSection(); require_once('page2.template.php'); echo $templ->renderSection('main'); ?>