Load the sprite sheet as one image, then each frame call drawImage() with the 9-argument form: source x/y/width/height picks the current frame from the sheet, destination x/y/width/height places it on the canvas. Clear the canvas and advance the frame index on a timer or via requestAnimationFrame.
At a glance
| Fact | Value | Source |
|---|---|---|
| drawImage() source rectangle args | sx, sy, sWidth, sHeight | developer.mozilla.org |
| iOS canvas size limit | 4096×4096 px | developer.mozilla.org |
| Phaser object for animated images | Sprite Game Object | docs.phaser.io |
Put every frame in one image (a sprite sheet), load it once, then on each draw call drawImage() with its 9-argument form: the first four numbers (sx, sy, sWidth, sHeight) crop the current frame out of the sheet, the last four place it on the canvas. “This example draws an image to the canvas using the drawImage() method” (MDN). Advance a frame index in a timer or requestAnimationFrame loop, and clear the canvas before each redraw so old frames don’t smear.
const img = new Image();
img.src = 'sheet.png';
let frame = 0;
const fw = 64, fh = 64, cols = 8;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const sx = (frame % cols) * fw;
ctx.drawImage(img, sx, 0, fw, fh, 0, 0, fw, fh);
frame++;
requestAnimationFrame(draw);
}
For browser games, watch canvas size limits – some mobile browsers, notably iOS, cap canvas dimensions at 4096x4096px, which limits how large or dense a single sheet can be. If you’d rather not manage frame math by hand, small libraries like Canvas-Sprite-Animations handle sequences and caching, and Phaser’s Sprite object supports built-in animation, tinting and tweening on top of Canvas or WebGL.
When using an AI coding agent, Playgama MCP lets the agent create the game, upload builds, and publish a sandbox playable link directly from Cursor or Claude Code.
Generating the sheet itself is a separate step from animating it – AI sprite tools like Ludo.ai’s Sprite Generator or TexturePacker (for packing existing frames) produce the PNG grid you then slice with drawImage.
Sources
- CanvasRenderingContext2D.drawImage() – MDN
- GitHub – IceCreamYou/Canvas-Sprite-Animations
- Sprite | Phaser Help
- Sprite Generator – Ludo.ai Docs
Related questions
Should each frame be a separate image or one sprite sheet?
Use one sprite sheet: it requires one HTTP request and one decoded image, which is faster to load and draw than swapping many separate image files per frame.
Why does my sprite sheet animation look smeared or leave trails?
You’re not calling clearRect() before each drawImage() call. Clear the whole canvas (or just the sprite’s previous rectangle) every frame before drawing the next one.
Can I pack existing frame images into one sheet automatically?
Yes, TexturePacker is a GUI and command-line tool built for exactly this: it creates sprite sheets or atlases from separate frame images, with a free Essential mode.
Last updated: 30 September 2026