- 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
1.9. Printing a Canvas
It’s often convenient to let users of your application access a canvas as an image. For example, if you implement a paint application, such as the one discussed in Chapter 2, users will expect to be able to print their paintings.
By default, although every canvas is a bitmap, it is not an HTML img element, and therefore users cannot, for example, right-click a canvas and save it to disk, nor can they drag a canvas to their desktop to print later on. The fact that a canvas is not an image is illustrated by the popup menu shown in Figure 1.18.
Figure 1.18. The right-click menu for a canvas
Fortunately, the Canvas API provides a method—toDataURL()—that returns a reference to a data URL for a given canvas. You can subsequently set the src attribute of an img element equal to that data URL to create an image of your canvas.
In Section 1.5, “Fundamental Drawing Operations,” on p. 22, you saw how to implement an analog clock with the Canvas API. Figure 1.19 shows a modified version of that application that lets you take a snapshot of the clock and display it as an image, as described above. As you can see from Figure 1.19, when you right-click on the ensuing image, you can save the image to disk, and because the clock image shown in the bottom screenshot is an img element, you can also drag the image to your desktop.
Figure 1.19. Using toDataURL()
The application shown in Figure 1.19 implements a common use case for printing a canvas: It provides a control—in this case, the Take snapshot button—that lets users take a snapshot of the canvas. The application displays that snapshot as an image, so users can right-click the image and save it to disk. Subsequently, when the user clicks the Return to Canvas button, the application replaces the image with the original canvas. Here’s a recipe for that use case:
In your HTML page:
- Add an invisible image to the page, and give the image an id, but no src.
- Use CSS to position and size the image to exactly overlap your canvas.
- Add a control to the page for taking a snapshot.
In your JavaScript:
- Get a reference to the invisible image.
- Get a reference to the snapshot control.
- When the user activates the control to take a snapshot:
- Invoke toDataURL() to get a data URL.
- Assign the data URL to the invisible image’s src attribute.
- Make the image visible and the canvas invisible.
- When the user activates the control to return to the Canvas:
- Make the canvas visible and the image invisible.
- Redraw the canvas as needed.
Let’s see how to translate that recipe to code. Example 1.11 lists the HTML for the application shown in Figure 1.19, and Example 1.12 lists the application’s JavaScript.
Example 1.11. Using toDataURL() to print a canvas: HTML
<!DOCTYPE
html
>
<head>
<title>
Clock</title>
<style>
body{
background:
#dddddd
;}
#canvas
{
position:
absolute
;left:
10px
;top:
1.5em
;margin:
20px
;border:
thin solid
#aaaaaa
;}
#snapshotImageElement
{
position:
absolute
;left:
10px
;top:
1.5em
;margin:
20px
;border:
thin solid
#aaaaaa
;}
</style>
</head>
<body>
<div
id
=
'controls'
>
<input
id
=
'snapshotButton'
type
=
'button'
value
=
'Take snapshot'
/>
</div>
<img
id
=
'snapshotImageElement'
/>
<canvas
id
=
'canvas'
width
=
'400'
height
=
'400'
>
Canvas not supported</canvas>
<script
src
=
'example.js'
></script>
</body>
</html>
Example 1.12. Using toDataURL() to print a canvas: JavaScript
var
canvas=
document.
getElementById
(
'canvas'
),
context=
canvas.
getContext
(
'2d'
),
snapshotButton=
document.
getElementById
(
'snapshotButton'
),
snapshotImageElement=
document.
getElementById
(
'snapshotImageElement'
),
loop;
// Clock drawing functions are omitted from this listing // in the interests of brevity. See Example 1.4 on p. 24 // for a complete listing of those methods. // Event handlers..................................................... snapshotButton.onclick=
function
(
e)
{
var
dataUrl;
if
(
snapshotButton.
value===
'Take snapshot'
)
{
dataUrl=
canvas.
toDataURL
();
clearInterval
(
loop);
snapshotImageElement.
src=
dataUrl;
snapshotImageElement.
style.
display=
'inline'
;
canvas.
style.
display=
'none'
;
snapshotButton.
value=
'Return to Canvas'
;
}
else
{
canvas.
style.
display=
'inline'
;
snapshotImageElement.
style.
display=
'none'
;
loop=
setInterval
(
drawClock,
1000
);
snapshotButton.
value=
'Take snapshot'
;
}
}
;
// Initialization................................................ context.
font=
FONT_HEIGHT+
'px Arial'
;
loop=
setInterval
(
drawClock,
1000
);
The application accesses the canvas and img elements and uses CSS absolute positioning to overlap the two elements. When the user clicks the Take snapshot button, the application obtains a data URL from the canvas and assigns it to the src attribute of the image. Then it shows the image, hides the canvas, and sets the text of the button to Return to Canvas.
When the user clicks the Return to Canvas button, the application hides the image, displays the canvas, and returns the text of the button to Take snapshot.