UNPKG

canvas-sprite

Version:

Render sprite animation with canvas, (0 dependencies)

142 lines (125 loc) 2.79 kB
import isCrossOrigin from './isCrossOrigin'; import setFPS from './setFPS'; export function loadImage(url) { return new Promise((resolve, reject) => { const img = new Image(); if (isCrossOrigin(url)) { img.crossOrigin = 'anonymous'; } img.onload = () => { resolve(img); }; img.onerror = () => { reject(Error(`${url} load failed`)); }; img.src = url; }); } function isInteger(num) { return typeof num === 'number' && parseInt(num) === num; } function CanvasSprite({ canvas, imageUrl, frames, fps = 12, loop = true, onEnd, onLoop }) { if (!canvas) { throw new Error('canvas is required'); } if (!imageUrl) { throw new Error('imageUrl is required'); } if (!isInteger(frames)) { throw new Error('frames is required and should be integer'); } if (!isInteger(fps)) { throw new Error('fps is required and should be integer'); } if (canvas.hasAttribute('data-cs-id')) { throw new Error('the canvas has sprite with it, call .destroy() first'); } canvas.setAttribute('data-cs-id', `cs-${Date.now()}`); let paused = false; let frameIndex = 0; let fpsIns = null; const context = canvas.getContext('2d'); let imgRef = null; function renderFrame() { if (!imgRef) { return; } const spriteWidth = imgRef.width; const spriteHeight = imgRef.height; if (frameIndex < frames) { context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage( imgRef, (frameIndex * spriteWidth) / frames, 0, spriteWidth / frames, spriteHeight, 0, 0, spriteWidth / frames, spriteHeight ); } frameIndex++; if (frameIndex === frames) { if (!loop) { fpsIns.cancel(); onEnd && onEnd(); } else { frameIndex = 0; onLoop && onLoop(); } } } function startAnim(img) { canvas.width = img.width / frames; canvas.height = img.height; imgRef = img; renderFrame(); fpsIns = setFPS(() => { if (paused) { return; } renderFrame(); }, fps); } if (imageUrl instanceof Image) { startAnim(imageUrl); } else { loadImage(imageUrl).then(img => { startAnim(img); }); } function play() { paused = false; } function pause() { paused = true; } function stop() { paused = true; frameIndex = 0; renderFrame(); } function destroy() { fpsIns && fpsIns.cancel(); context && context.clearRect(0, 0, canvas.width, canvas.height); canvas && canvas.removeAttribute('data-cs-id'); } return { play, pause, stop, destroy }; } CanvasSprite.loadImage = loadImage; export default CanvasSprite;