I've been trying to find an answer for a while but most searches return results for animating shapes not frame animation. Given a canvas
with a 2d
context to which I draw sprites with drawImage
, what's the most efficient way to create multiple frames for an animated image? I'm looking for something like animated gif but using canvas, where I have a number of frames (eg: 4) with a fixed rate (eg: 500 ms) and I paint different tiles on each frame.
I need this for a tileset engine I thought of prototyping: The canvas is static by default, to support animated tiles like water you'd need multiple frames. The most obvious solution feels like having multiple canvas elements and showing / hiding them in order, but I'd like to check if there's a more efficient way, in case canvas supports multiple layers or CSS might work.
If you want to animate multiple frames efficiently in an HTML5 , you don’t need multiple canvas elements. Instead, you can update a single canvas by drawing different frames at regular intervals.
Efficient Approach: Using requestAnimationFrame + setInterval The best way to handle this is:
Here’s an example:
<canvas id="gameCanvas" width="200" height="200"></canvas>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const spriteSheet = new Image();
spriteSheet.src = "sprite.png"; // Your sprite sheet containing all frames
const frameWidth = 64; // Width of a single frame
const frameHeight = 64; // Height of a single frame
const totalFrames = 4; // Total frames in the animation
const frameRate = 500; // Change frame every 500ms
let currentFrame = 0;
spriteSheet.onload = () => {
setInterval(() => {
currentFrame = (currentFrame + 1) % totalFrames;
}, frameRate);
animate();
};
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear previous frame
ctx.drawImage(
spriteSheet,
currentFrame * frameWidth, 0, frameWidth, frameHeight, // Source from sprite sheet
0, 0, frameWidth, frameHeight // Draw onto the canvas
);
requestAnimationFrame(animate);
}
</script>
Why This Works Well
If you’re working on a tile-based engine, you can store animation states for different tiles and only update the ones that need it.