HTML5 Canvas: Creating a screenshot from multiple canvases in JavaScript

Programmatically creating screenshots from JavaScript of your canvas element is fairly straightforward; but how do you do it when your game or scene is composed of multiple overlaid canvases?

This example makes use of the canvas caching and it links into the animation loop for starting and stopping – your mileage may vary.

For simplicity, lets say we have 4 canvas elements in use, all of the same size (500×500) used in the following order:

  1. A far background: canvasFar
  2. A near background for a touch of Parallax scrolling: canvasNear
  3. A layer for player characters and other objects: canvasSprites
  4. A layer for special effects: canvasEffects

[code lang=”javascript”]
function TakeScreenshot() {
StopAnimating(); // Stop the animation loop

var bufferScreenshot = CreateCanvasCached("Screenshot");
bufferScreenshot.height = 500; bufferScreenshot.width = 500;
var contextScreenshot = bufferScreenshot.getContext("2d");
// Draw the layers in order
contextScreenshot.drawImage(
document.getElementById("canvasFar"), 0, 0, 500, 500);
contextScreenshot.drawImage(
document.getElementById("canvasNear"), 0, 0, 500, 500);
contextScreenshot.drawImage(
document.getElementById("canvasSprites"), 0, 0, 500, 500);
contextScreenshot.drawImage(
document.getElementById("canvasEffects"), 0, 0, 500, 500);

// Save to a data URL as a jpeg quality 9
var imgUrl = bufferScreenshot.toDataURL("image/jpeg", .9);

StartAnimating(); // Restart the animation loop
return imgUrl;
}
[/code]

Now calling TakeScreenshot() will return a data URL that contains the image – with this you can:

  • Set the src of an image element or css background
  • Open it in a new window to display it as an image (unfortunately you can’t set the content-disposition or filename of a data URL for automatic download)
  • Send it to your sever to base64 decode and create an image file which you can then to popup a download or embed in a page which can then be shared, tweeted, posted to Google+ or Facebook.
  • Use it as source image for more canvas fun or a WebGl texture

UPDATE: There is a toBlob() method on Canvas that allows the saving of generated files on the client-side which is coming in Chrome 14, hopefully other browsers will follow suit.

This should all work fine.  However if you are using images from different domains or a multiple sub-domains – either by using a CDN or for paralleling requests across domain names you will receive a:

SECURITY_ERR: DOM Exception 18

This is a security protection to ensure your code isn’t grabbing images it shouldn’t be, and sending them back to your server. I’ll post about how to work with this in a future post.