async function initSprites( img, sprite_width = img.width, sprite_height = img.height ) {
// you would have to make the sprite factory logic based on your actual spritesheet,
// here Im using a simple fixed-size grid from wikimedia
const sprites = [];
for( let y = 0; y < img.height; y += sprite_height) {
for( let x = 0; x < img.width; x += sprite_width ) {
sprites.push(
await createImageBitmap( img, x, y, sprite_width, sprite_height )
);
}
}
return sprites;
}
async function loadImage( url ) {
var img = new Image();
img.crossOrigin = 'anonymous';
await new Promise( (res, rej) => {
img.onload = (e) => res( img );
img.onerror = rej;
img.src = url;
} );
return img;
}
async function init() {
const url = "https://upload.wikimedia.org/wikipedia/commons/b/be/SpriteSheet.png";
const FPS = 10;
const sprite_width = 132;
const sprite_height = 97;
// we don't keep any reference to the Image
const sprites = await initSprites( await loadImage( url ), sprite_width, sprite_height );
const canvas = document.getElementById( 'canvas' );
const ctx = canvas.getContext( '2d' );
const frame_time = 1000 / FPS;
let sprite_index = 0;
let lastTime = performance.now();
requestAnimationFrame( update );
function update( t ) {
if( t - lastTime > frame_time ) {
lastTime = t;
sprite_index = (sprite_index + 1) % sprites.length;
draw();
}
requestAnimationFrame( update );
}
function draw() {
ctx.clearRect( 0, 0, canvas.width, canvas.height );
// we just reproduce the original spritesheet
// but animated
let inner_index = 0;
for(let y = 0; y < 3; y++) {
for( let x = 0; x < 4; x ++ ) {
inner_index ++;
const index = (sprite_index + inner_index) % sprites.length;
const sprite = sprites[ index ];
ctx.drawImage( sprite, x * sprite_width, y * sprite_height );
}
}
}
}
// for Safari and IE
monkeyPatchCreateImageBitmap();
init().catch( console.error );
// a very poor monkey patch, only allowing HTMLImageElement as source
// returns an HTMLCanvasElement
function monkeyPatchCreateImageBitmap() {
if( typeof window.createImageBitmap === 'undefined' ) {
window.createImageBitmap = monkeyPatch;
}
function monkeyPatch( img, sx = 0 , sy = 0, sw = img.width, sh = img.height ){
const canvas = document.createElement( 'canvas' );
canvas.width = sw;
canvas.height = sh;
canvas.getContext( '2d' )
.drawImage( img, sx, sy, sw, sh, 0, 0, sw, sh );
canvas.close = (e) => canvas.width = 0;
return Promise.resolve( canvas );
};
}
<canvas id="canvas" width="528" height="291"></canvas>