HTML5 Canvas Essentials
- 1.1. The canvas Element
- 1.2. Canvas Contexts
- 1.3. Canonical Examples in This Book
- 1.4. Getting Started
- 1.5. Fundamental Drawing Operations
- 1.6. Event Handling
- 1.7. Saving and Restoring the Drawing Surface
- 1.8. Using HTML Elements in a Canvas
- 1.9. Printing a Canvas
- 1.10. Offscreen Canvases
- 1.11. A Brief Math Primer
- 1.12. Conclusion
In 1939, Metro-Goldwyn-Mayer Studios released a film that, according to the American Library of Congress, was destined to become the most watched film in history. The Wizard of Oz is the story of a young girl named Dorothy and her dog Toto, who are transported by a violent tornado from Kansas in the central United States to the magical land of Oz.
The film begins in Kansas and is shot in a bland and dreary black-and-white. When Dorothy and Toto arrive in the land of Oz however, the film bursts into vibrant color, and the adventure begins.
For more than a decade, software developers have been implementing bland and dreary web applications that do little more than present bored-to-death users with a seemingly unending sequence of banal forms. Finally, HTML5 lets developers implement exciting desktop-like applications that run in the browser.
In this HTML5 land of Oz, we will use the magical canvas element to do amazing things in a browser. We will implement image panning, as shown in Figure 1.1; an interactive magnifying glass; a paint application that runs in any self-respecting browser and that also runs on an iPad; several animations and games, including an industrial-strength pinball game; image filters; and many other web applications that in another era were almost entirely the realm of Flash.
Figure 1.1. Canvas offers a powerful graphics API
Let’s get started.
1.1. The canvas Element
The canvas element is arguably the single most powerful HTML5 element, although, as you’ll see shortly, its real power lies in the Canvas context, which you obtain from the canvas element itself. Figure 1.2 shows a simple use of the canvas element and its associated context.
Figure 1.2. Hello canvas
The application shown in Figure 1.2 simply displays a string, approximately centered in the canvas itself. The HTML for that application is shown in Example 1.1.
The HTML in Example 1.1 uses a canvas element and specifies an identifier for the element and the element’s width and height. Notice the text in the body of the canvas element. That text is known as the fallback content, which the browser displays only if it does not support the canvas element.
Besides those two elements, the HTML in Example 1.1 uses CSS to set the application’s background color and some attributes for the canvas element itself. By default, a canvas element’s background color matches the background color of its parent element, so the CSS sets the canvas element’s background color to opaque white to set it apart from the application’s light gray background.
The HTML is straightforward and not very interesting. As is typically the case for Canvas-based applications, the interesting part of the application is its JavaScript. The JavaScript code for the application shown in Figure 1.2 is listed in Example 1.2.
Example 1.1. example.html
<!DOCTYPE
html
>
<html>
<head>
<title>
A Simple Canvas Example</title>
<style>
body{
background:
#dddddd
;}
#canvas
{
margin:
10px
;padding:
10px
;background:
#ffffff
;border:
thin inset
#aaaaaa
;}
</style>
</head>
<body>
<canvas
id
=
'canvas'
width
=
'600'
height
=
'300'
>
Canvas not supported</canvas>
<script
src
=
'example.js'
></script>
</body>
</html>
Example 1.2. example.js
var
canvas=
document.
getElementById
(
'canvas'
),
context=
canvas.
getContext
(
'2d'
);
context.
font=
'38pt Arial'
;
context.
fillStyle=
'cornflowerblue'
;
context.
strokeStyle=
'blue'
;
context.
fillText
(
'Hello Canvas'
,
canvas.
width/
2
-
150
,
canvas.
height/
2
+
15
);
context.
strokeText
(
'Hello Canvas'
,
canvas.
width/
2
-
150
,
canvas.
height/
2
+
15
);
The JavaScript in Example 1.2 employs a recipe that you will use in your Canvas-based applications:
- Use document.getElementById() to get a reference to a canvas.
- Call getContext('2d') on the canvas to get the graphics context (note: the ‘d’ in ‘2d’ must be lowercase).
- Use the context to draw in the canvas.
After obtaining a reference to the canvas’s context, the JavaScript sets the context’s font, fillStyle, and strokeStyle attributes and fills and strokes the text that you see in Figure 1.2. The fillText() method fills the characters of the text using fillStyle, and strokeText() strokes the outline of the characters with strokeStyle. The fillStyle and strokeStyle attributes can be a CSS color, a gradient, or a pattern. We briefly discuss those attributes in Section 1.2.1, “The 2d Context,” on p. 9 and take a more in-depth look at both the attributes and methods in Chapter 2.
The fillText() and strokeText() methods both take three arguments: the text and an (x, y) location within the canvas to display the text. The JavaScript shown in Example 1.2 approximately centers the text with constant values, which is not a good general solution for centering text in a canvas. In Chapter 3, we will look at a better way to center text.
1.1.1. Canvas Element Size vs. Drawing Surface Size
The application in the preceding section sets the size of the canvas element by setting the element’s width and height attributes. You can also use CSS to set the size of a canvas element, as shown in Example 1.3; however, using CSS to size a canvas element is not the same as setting the element’s width and height attributes.
Example 1.3. Setting element size and drawing surface size to different values
<!DOCTYPE
html
>
<head>
<title>
Canvas element size: 600 x 300, Canvas drawing surface size: 300 x 150</title>
<style>
body{
background:
#dddddd
;}
#canvas
{
margin:
20px
;padding:
20px
;background:
#ffffff
;border:
thin inset
#aaaaaa
;width:
600px
;height:
300px
;}
</style>
</head>
<body>
<canvas
id
=
'canvas'
>
Canvas not supported</canvas>
<script
src
=
'example.js'
></script>
</body>
</html>
The difference between using CSS and setting canvas element attributes lies in the fact that a canvas actually has two sizes: the size of the element itself and the size of the element’s drawing surface.
When you set the element’s width and height attributes, you set both the element’s size and the size of the element’s drawing surface; however, when you use CSS to size a canvas element, you set only the element’s size and not the drawing surface.
By default, both the canvas element’s size and the size of its drawing surface is 300 screen pixels wide and 150 screen pixels high. In the listing shown in Example 1.3, which uses CSS to set the canvas element’s size, the size of the element is 600 pixels wide and 300 pixels high, but the size of the drawing surface remains unchanged at the default value of 300 pixels × 150 pixels.
And here is where things get interesting because when a canvas element’s size does not match the size of its drawing surface, the browser scales the drawing surface to fit the element. That effect is illustrated in Figure 1.3.
Figure 1.3. Top: element and coordinate system = 600 × 300; bottom: element = 600 × 300, coordinate system = 300 × 150
The application shown at the top of Figure 1.3 is the application that we discussed in the preceding section. It sets the canvas element’s size with the element’s width and height attributes, setting both the element’s size and the size of the drawing surface to 600 pixels × 300 pixels.
The application shown at the bottom of Figure 1.3 is the application whose HTML is shown in Example 1.3. That application is identical to the application in the preceding section, except that it uses CSS to size the canvas element (and has a different title in the window’s title bar).
Because the application shown in the bottom screenshot in Figure 1.3 uses CSS to size the canvas element and does not set the element’s width or height attributes, the browser scales the drawing surface from 300 pixels × 150 pixels to 600 pixels × 300 pixels.
1.1.2. The Canvas API
The canvas element does not provide much of an API; in fact, that API offers only two attributes and three methods that are summarized in Table 1.1 and Table 1.2.
Table 1.1. canvas attributes
Attribute |
Description |
Type |
Allowed Values |
Default |
width |
The width of the canvas’s drawing surface. By default, the browser makes the canvas element the same size as its drawing surface; however, if you override the element size with CSS, then the browser will scale the drawing surface to fit the element. |
non-negative integer |
Any valid non-negative integer. You may add a plus sign or whitespace at the beginning, but technically, you cannot add a px suffix. |
300 |
height |
The height of the canvas’s drawing surface. The browser may scale the drawing surface to fit the canvas element size. See the width attribute for more information. |
non-negative integer |
Any valid non-negative integer. You may add a plus sign or whitespace at the beginning, but technically, you cannot add a px suffix. |
150 |
Table 1.2. canvas methods
Method |
Description |
getContext() |
Returns the graphics context associated with the canvas. Each canvas has one context, and each context is associated with one canvas. |
toDataURL(type, quality) |
Returns a data URL that you can assign to the src property of an img element. The first argument specifies the type of image, such as image/jpeg, or image/png; the latter is the default if you don’t specify the first argument. The second argument, which must be a double value from 0 to 1.0, specifies a quality level for JPEG images. |
toBlob(callback, type, args...) |
Creates a Blob that represents a file containing the canvas’s image. The first argument to the method is a function that the browser invokes with a reference to the blob. The second argument specifies the type of image, such as image/png, which is the default value. The final arguments represent a quality level from 0.0 to 1.0 inclusive, for JPEG images. Other arguments will most likely be added to this method in the future to more carefully control image characteristics. |