This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

HTML Canvas and Images

6:50 JavaScript lesson by

In addition to vector drawing, you can draw bitmap images into a canvas, and also retrieve a bitmap based on the content in a canvas.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

In addition to vector drawing, you can draw bitmap images into a canvas, and also retrieve a bitmap based on the content in a canvas.

Avatar
Sam

Quality video! That last bit about jpg compression helped me reduce quite a bit of server load on a current project.

While it's very useful to draw vector shapes such as lines, rectangles, curves, arcs, and text into a canvas, there are times when you want to draw a bitmap image into the canvas, as well. Of course, it's often useful to get a bitmap out of a canvas that you've drawn into.

The 2D rendering context method for drawing an image into a canvas is, not surprisingly, drawImage. It takes an image and various numerical arguments to specify the position and or size of where the image is drawn.

The simplest version specifies the X, Y position to draw the image at on the canvas. But first of all, what is the image that gets passed into this method? It's simply an HTML image element.

The most obvious way to get an image element is to define the image in the HTML document with an ID like so. Then, get a reference to it using document.getElementById or some other selection method.

Of course, doing it this way you need to make sure that the image is fully loaded before trying to draw it. We're using a window on load handler here, so we'll be

But remember that the document-ready functionality of many frameworks fires when the HTML document itself is loaded and been parsed, but before other content like images has been loaded.

Here, we'll draw the image to the canvas at a position of 0, 0, the top-left corner. Now, you can see two copies of the image. The original and the image element itself, and the copy down below, drawn to the canvas.

But a far more dynamic and useful way of doing this is to create the image element with JavaScript, load an image into it, and then, draw that to the canvas after the image has loaded in.

I'll remove the image element from the HTML and instead of selecting the element I'll use document.createElement to create it. Then, I'll set its source property and set up an event listener to know when it has loaded.

In that handler, I'll draw the loaded image to the canvas just like before. Now, we see the canvas with the image drawn into it. We don't see the image itself, because it was not added to the document.

Now, let's look at the other parameters of the drawImage method. As I said, we're using two parameters now, which are interpreted as the X, Y point to position the drawn image.

If I change these, we can see the image being drawn at different locations. These parameters are technically called destination X and destination Y, because they specify the location of the destination image.

The second version of this method takes four numerical parameters after the image. In addition to the destination X and Y, this has destination width and height, creating a rectangle in which to draw the image. By default, the image will be drawn to the canvas at its original size.

I happen to know that this image is exactly 600 by 300 pixels, I can add the next two parameters at 300, 150, which draws the image at half size.

Realize that it's up to you to calculate these numbers to maintain the aspect ratio of the image. If I were to enter, say, 300, 300, you can see that the image is stretched out of proportion.

Now, the final version of the drawImage method takes that image plus eight numerical parameters. These eight numbers form two rectangles. The first rectangle is used to specify a portion of the source image.

These first four parameters are source X, source Y, source width, and source height. All other versions of the method draw the entire source image to the canvas. This allows you to specify a portion of the image.

Again, the source image is 600 by 300. I can specify the source rectangle as 280, 20, 150, 150. I'm creating a 150-pixel square at position 280, 20. I can then use the next four parameters to draw that square anywhere to the canvas, at any size.

I'll adjust the destination rectangle to be square, as well. I've essentially cropped that image. I can draw that square smaller and I can move it around by drawing at different locations on the canvas.

A common use for this version of the method is in drawing sprite sheets in a game. A sprite sheet is a small animation, where all the frames of the animation are packed into a single bitmap.

By specifying different source rectangles over time, you're able to play back the animation. Here's an example of a sprite sheet. Note that it contains four rows and four columns of smaller images.

Here's the code that will animate that. I won't go into it all in detail here, but I've set up an interval that will run 15 times per second. Here, I'm calculating a different source rectangle in each frame. But I'm drawing it to the same destination rectangle. The result? A horse galloping.

That covers getting a bitmap image into a canvas. But how about getting an image out of one? In this example, I'm creating a canvas with JavaScript and drawing a bunch of random lines through it. Note that the canvas is not added to the HTML document, nothing is visible on the page yet.

You can transform the image in this canvas to a bitmap by calling canvas.toDataURL. This returns the image data encoded into a long string.

This starts with the string data, with some info about the image, and then, all the bytes of the image itself. You can then directly assign this string to an HTML element's source property to display that image.

Here, I'll create an image element and I'll set its source property to canvas.toDataURL. Finally, I'll add that image to the document body, and here's the image. Now by default, this creates a PNG image. If you want to explicitly set this, you can pass in the string image/png.

The other option is image/jpg. Now, because JPEG support compression, you can add a second parameter here, which is a number between 0 and 1, indicating how much compression to use, where 1 is full quality minimal compression and 0 is lowest quality with very high compression.

This string could also be sent to a server and potentially converted into an actual image file and saved there, or downloaded by a user. This gives a user a way to download an image dynamically created in canvas.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?