Example Title
book cover
book cover back

Retained-mode graphics with HTML5 Canvas

Canvas implements immediate-mode graphics. Double buffering notwithstanding, Canvas immediately draws everything you tell it to, and then it immediately forgets what it has drawn. Other graphics systems, such as SVG, implement retained-mode graphics, meaning they retain a list of objects that they draw. Immediate-mode generally performs better than retained-mode, but is not as convenient.

This example implements retained-mode graphics in Canvas by maintaining a list of polygons that you can manipulate. Here's how to use the application:

Click and drag anywhere on the grid background to interactively create a polygon. When you release the mouse, the application adds the polygon to the list.

You can move polygons around by dragging them with the mouse.

If you click inside a polygon without dragging the mouse, the application annotates the polygon with a rotation wheel. As you subsequently move the mouse, the application rotates the polygon in accordance with the mouse. Subsequently, when you click the mouse, the application removes the rotation annotations and sets the polygon's rotation. (If the polygon is too small, the application doesn't draw the rotation wheel, but you still can rotate the polygon by moving the mouse.)

Note: This example uses jscolor (see jscolor.com) for the color pickers. I do not use the color picker's in the book's example.

Stroke: Fill:
Sides: Start angle: Fill
Canvas not supported


Traditionally, animators drew key frames and apprentices filled in the frames inbetween.

Often, tween frames follow a non-linear progression; for example, a ball bouncing off the floor loses speed as it rises. You can model non-linear motion with a tweening algorithm that adjusts the animation rate as it iterates through the tween frames. In this example, if you select Ease In, the runner's speed—and the rate at which her animation cells are updated—start out slowly, and speed up as the animation progresses. Ease Out is the opposite effect.

Some graphics systems, such as Flash, let you select tweening algorithms. Canvas does not come with tweening built-in, but you can implement it yourself, as this example shows.

This example controls both the rate at which the runner moves, and the rate at which her animation cells are updated, by applying a tweening algorithm to the animation's time. The technique is simple:

The application animates the runner based on the elapsed time of the animation, but it obtains that elapsed time from a timer that erroneously reports the time. For Ease In, the timer initially reports times that are much less than the actual time, but as the animation progresses, the timer narrows the gap between the time it reports and the actual elapsed time, until, at the end of the animation, the timer reports the correct elapsed time. By controlling the flow of time, the application indirectly controls time's derivatives: motion and animation rate.

Canvas not supported
Linear Ease In Ease Out Ease In/Out

Translating the Canvas Coordinate System

As you drag the image panner's viewport, the image panner constantly redraws the image in the large canvas, always drawing the image at the same location in the canvas: (0,0). The image appears to move, however, because the image panner also constantly translates the canvas's coordinate system in accordance with the position of the viewport.

Being able to translate a canvas's coordinate system is a powerful feature of the Canvas API that facilitates the development of interesting features such as side-scrolling backgrounds and parallax.

Like the image panner, the sliders are Canvas-based custom controls. As you move a slider's knob, the slider fires events to the image panner, which responds by adjusting the size or opacity of its control canvas.

Canvas not supported
Canvas not supported Canvas not supported
Only the magnifying glass is currently available.

The canvas underneath this notice is now an image. For desktop browsers, you can Right-click on the image to save it to disk. On the iPad, touch and hold the image for about a second, and you will see a popup menu.

When you click the Back to Paint button, the image will revert to the canvas.

Stroke: Fill: Line width:
Canvas not supported Canvas not supported

The yellow circles represent control-points for a cubic bezier curve and the red circles represent the curve's end-points. You can drag any of them to change the shape of the curve. When you are done adjusting the curve's shape, click anywhere outside of the control- and end-points to finalize the curve.

Canvas-based Controls

The sliders in this example are Canvas-based controls. When you need a control that is outside the limited set of HTML elements, for example a magnifying glass or an image panner, it's convenient to be able to implement your own custom controls. You may also wish to implement custom controls if you want a consistent look across browsers.

The sliders in this example are canvas elements wrapped in a DIV, implemented as JavaScript objects that fire events to registered listeners when a user moves a slider's knob.

There is currently a nascent specification for HTML5 Web Components under development. In the meantime, this example illustrates how to implement ad-hoc web components.

Note: Opera and IE9/10 do not draw the sliders correctly, see w3cschools.com.


A Paint Application

This application, which runs in HTML5-capable desktop browsers and the iPad (best with iOS 5.0 and above) uses many features of the Canvas drawing API to draw and erase shapes and text.

The eraser, which you activate by selecting the bottom icon, is implemented using the Canvas's clipping region. As you drag the eraser, the application constantly redraws the entire grid background—clipped to the eraser's circle—which effectively erases anything within that circle.

If you click the Take a snapshot button in the upper-left corner of the application, the icons and controls will fade from view, and the drawing canvas will turn into an image that you can drag to your desktop, or right-click to save to disk.

The slinky tool, represented by the icon above the eraser icon, is the result of a failed attempt to implement the eraser.


A Magnifying Glass

This application illustrates drawing and scaling images with the Canvas context's drawImage() method and setting the context's clipping region with clip().

As you drag the magnifying glass, the application draws the pixels underneath the magnifying glass lens, scaled at the selected scale, back into the canvas. When the application draws those scaled pixels, it restricts them to the magnifying glass lens by setting the clipping region to that circle.

The sliders at the top of the application that control the size of the magnifying glass lens and the magnification level are Canvas-based controls.

On an iPad, you can pinch and zoom to control the magnification level and if you're using Chrome 10+, you can drop images from your desktop on the application's image. It doesn't work on all versions of Chrome, though—some versions of Chrome have FileSystem API bugs.

Note: Opera and IE9/10 do not draw the sliders correctly, see w3cschools.com. Opera also does not consistently resize the magnifying glass lens, so the sliders, although you can manipulate them, produce no effects on Opera.