Canvas image basics with ctx.drawImage

When it comes to canvas and images most of the time that means knowing a thing or two about how to use the drawImage 2d context method that can be used to render all or part of an image that has been loaded. However that is just it the image needs to be loaded first, this alone can complicate matters when it comes to making a vanilla javaScript canvas project. There are other ways of creating and working with images in canvas as well though, some of which do not need an external resource loaded first, so lets take a looks at some canvas image basics.

1 - Canvas image must know basics

This is a post on the HTML canvas element, and using images with a canvas project. This is not a getting started post with canvas, let alone javaScript in general. If you are new to javaScript and canvas you might want to start out elsewhere.

In canvas there is the drawImage method that is used to draw an image onto a canvas. WIth the drawImage method an external image, a Data URL, or another canvas element can be used as a source. There is also ways to create an image from a canvas, and create images with just context drawing methods using no external assets at all which I often seem to prefer for starters at least, and more often then not the only way to go about making graphics.

2 - Canvas drawImage method basic example

Here I have a basic example of the drawImage method. To use the draw image method with an external image that external image must be loaded first.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<html>
<head>
<title>canvas image</title>
</head>
<body>
<canvas id="the-canvas" width="128" height="128"></canvas>
<script>
var canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
// create an instance of image
var img = new Image();
// what to do when the image is loaded
img.addEventListener('load', function(){
// draw an image
ctx.drawImage(img,32,32);
});
// when src is set the download will begin
img.src='./pic.png';
</script>
</body>
</html>

In this example I am giving the drawImage method just three arguments in this case the whole image will be drawn at the given location set by the following two arguments after the image is given. However the drawImage method can be given up to nine arguments in total. SO lets look at some more examples of drawImage.

3 - Canvas images and scaling with the drawImage method

The drawImage method can be given five arguments in total, just like the simple three argument example the first is a reference to the image that is to be drawn to the canvas. In addition just like before the second two arguments set the location that the image is to be drawn at in the canvas as well. However now an additional two arguments can be used to scale the image when it is drawn to the canvas as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
// create an instance of image
var img = new Image();
// what to do when the image is loaded
img.addEventListener('load', function(){
// destination x and y
var dx = 0,dy = 0,
// destination width and height
dw = 64,dh = 64;
// draw an image
ctx.drawImage(img,dx,dy,dw,dh);
});
// when src is set the download will begin
img.src='./pic.png';

Doing this eats up a little overhead, it is best to keep your assets native, but on the fly scaling can be preformed.

4 - Canvas images and sprite sheets

So there is then the most complicated use case example of the drawImage method that can be used to set the source location and size in the image to be drawn, as well as the destination values when it comes to the location and scale in the canvas as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
// create an instance of image
var img = new Image();
// what to do when the image is loaded
img.addEventListener('load', function(){
// image source x and y
var sx = 32, sy =0,
// image source width and height
sw = 32, sh = 32,
// destination x and y
dx = 0,dy = 0,
// destination width and height
dw = 64,dh = 64;
// draw the image
ctx.drawImage(img,sx,sy,sw,sh,dx,dy,dw,dh);
});
// when src is set the download will begin
img.src='./pic-sheet.png';

In this example the four arguments given after the image are not the values that have to do with the location and size when drawing to the canvas, but the same values when pulling image data from the source image. So this is useful when working with a spite sheet where there is a collection of frames in a static image format.

5 - Using another canvas and an image source for drawImage

Another canvas element can be used in place of an image element for the first argument of the drawImage method. To do this I just need to create an extra canvas element by one way or another, and the extra canvas element does not need to be appended to the html at all.

Say I want to work out a sprite sheet with canvas and javaScript that might take a lot of overhead to create. I could draw to the sheet canvas once, and then reference it in my other main canvas when it comes to drawing from it. This can be used with other techniques like layering to help make canvas projects run smoother.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<html>
<head>
<title>canvas image</title>
</head>
<body>
<canvas id="the-canvas"></canvas>
<script>
// sheet
var sheet = document.createElement('canvas'),
ctxSheet = sheet.getContext('2d');
sheet.width = 32 * 16;
sheet.height = 32;
var drawPlayerSheet = function (ctx, canvas, cells) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var i = 0,
r,
x,
y;
cells = cells || 30;
ctx.save();
ctx.lineWidth = 3;
while (i < cells) {
r = Math.PI * 2 * (i / cells),
x = Math.cos(r) * 16 + 16,
y = Math.sin(r) * 16 + 16;
ctx.beginPath();
ctx.arc(16, 16, 8, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(16, 16);
ctx.lineTo(x, y);
ctx.stroke();
ctx.translate(32, 0);
i += 1;
}
ctx.restore();
};
drawPlayerSheet(ctxSheet, sheet, 16);
// using the sheet with
// the main canvas
var canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
canvas.width = 320;
canvas.height = 240;
var cellIndex = 0,
x = 160,
y = 120;
var loop = function () {
requestAnimationFrame(loop);
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(-16, -16);
// using the other 'sheet' canvas as an image source
ctx.drawImage(sheet, 32 * cellIndex, 0, 32, 32, x, y, 32, 32);
ctx.restore();
cellIndex += 1;
cellIndex %= 16;
};
loop();
</script>
</body>
</html>