Canvas Images
Learn how to load images asynchronously and paint them onto the canvas with drawImage(), from simple placement to scaling and sprite-sheet cropping.
Getting an Image onto the Canvas
The canvas API cannot draw a file path directly — it draws pixel data from an already-decoded image source such as an <img> element, another <canvas>, a <video> frame, or an ImageBitmap. The most common pattern is to create an Image object in JavaScript, point its src at a file, wait for the browser to decode it, and only then call drawImage().
Example 1: Load and Draw
<!DOCTYPE html>
<html>
<body>
<canvas id="scene" width="300" height="200" style="border:1px solid #ccc;"></canvas>
<script>
const canvas = document.getElementById('scene');
const ctx = canvas.getContext('2d');
const logo = new Image();
logo.src = 'assets/logo.png';
// drawImage() must not run until the browser has decoded pixel data
logo.onload = () => {
ctx.drawImage(logo, 20, 20);
};
</script>
</body>
</html>The Three drawImage() Signatures
Scaling and Cropping in Practice
Because drawImage() always scales the source rectangle to fit the destination rectangle, the same method handles two very different jobs: shrinking or stretching a whole photo to fit a canvas (the four-argument form), and pulling a single animation frame out of a sprite sheet before enlarging it on screen (the nine-argument form). Both examples below reuse the same canvas and image-loading pattern from Example 1.
Example 2: Scale to Fit and Center
<!DOCTYPE html>
<html>
<body>
<canvas id="scene" width="300" height="200" style="border:1px solid #ccc;"></canvas>
<script>
const canvas = document.getElementById('scene');
const ctx = canvas.getContext('2d');
const photo = new Image();
photo.src = 'assets/photo.jpg';
photo.onload = () => {
const scale = Math.min(
canvas.width / photo.width,
canvas.height / photo.height
);
const w = photo.width * scale;
const h = photo.height * scale;
const x = (canvas.width - w) / 2;
const y = (canvas.height - h) / 2;
ctx.drawImage(photo, x, y, w, h);
};
</script>
</body>
</html>Example 3: Sprite Sheet Cropping
<!DOCTYPE html>
<html>
<body>
<canvas id="scene" width="340" height="300" style="border:1px solid #ccc;"></canvas>
<script>
const canvas = document.getElementById('scene');
const ctx = canvas.getContext('2d');
const sheet = new Image();
sheet.src = 'assets/hero-sheet.png';
const frameWidth = 64;
const frameHeight = 64;
let frameIndex = 0;
sheet.onload = () => {
setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const sx = frameIndex * frameWidth;
ctx.drawImage(
sheet,
sx, 0, frameWidth, frameHeight, // source rectangle
100, 100, frameWidth * 2, frameHeight * 2 // destination rectangle
);
frameIndex = (frameIndex + 1) % 6;
}, 120);
};
</script>
</body>
</html>- Generating thumbnails and avatar previews from a larger source image
- Playing sprite-sheet animations frame by frame in 2D games
- Watermarking or stamping a logo onto user-uploaded photos
- Building simple image editors that redraw a photo after each filter or crop
- Compositing background art and textures behind UI elements drawn with the canvas API
Exercise: Canvas Images
What must happen before drawImage() reliably draws an image element onto canvas?