mason-sprite
v0.1.8
Published
Lightweight sprite sheet animation for React, Vue, and Svelte
Maintainers
Readme
mason-sprite
Latest release: v0.1.8
Lightweight sprite sheet animation for React, Vue, and Svelte.
Drop in a uniform-grid PNG or WebP sheet, set rows, cols, and fps — CSS or Canvas rendering with no timeline editor. Framework components are exported as MasonSprite to avoid clashing with other Sprite components.
Docs & demo: mason-sprite.com
When to use
- Loop only → animated WebP
<img>(simpler, no JS) - play / pause / segments / frame control → mason-sprite
Preview
| Sprite sheet (2 × 5) | Rendered | | :---: | :---: | | | |
Install
npm install mason-sprite| Framework | Peer dependencies |
| --- | --- |
| React | react, react-dom |
| Vue 3 | vue |
| Svelte | svelte |
Usage
React
import { useRef } from 'react';
import { MasonSprite, type MasonSpriteHandle } from 'mason-sprite/react';
const ref = useRef<MasonSpriteHandle>(null);
<MasonSprite
ref={ref}
src="/sprites/cat-run.webp"
rows={2}
cols={5}
fps={10}
loop
width="8rem"
height="8rem"
/>
// ref.current?.playAnimation('walk');Vue
<script setup>
import { MasonSprite } from 'mason-sprite/vue';
</script>
<template>
<MasonSprite
src="/sprites/cat-run.webp"
:rows="2"
:cols="5"
:fps="10"
loop
width="8rem"
height="8rem"
/>
</template>Svelte
<script>
import { MasonSprite } from 'mason-sprite/svelte';
</script>
<MasonSprite
src="/sprites/cat-run.webp"
rows={2}
cols={5}
fps={10}
loop
width="8rem"
height="8rem"
/>Vanilla JS
import { SpriteAnimator } from 'mason-sprite';
const animator = new SpriteAnimator({
src: '/sprites/cat-run.webp',
rows: 2,
cols: 5,
fps: 10,
loop: true,
width: '8rem',
height: '8rem',
});
animator.attach(document.getElementById('sprite')!);
// Play a frame range
animator.playSegment({ start: 0, end: 4 });
// Or use a named clip map
const walk = new SpriteAnimator({
src: '/sprites/hero.webp',
rows: 4,
cols: 5,
animations: {
idle: { start: 0, end: 3 },
walk: { start: 5, end: 9 },
},
});
walk.attach(document.getElementById('hero')!);
walk.playAnimation('walk');
// Reverse playback
animator.updateOptions({ reverse: true });Rendering
mason-sprite supports two renderers. The default CSS renderer is optimized for compositor-friendly updates; use canvas when you need pixel-level control or off-screen export.
| Renderer | How it works | Best for |
| --- | --- | --- |
| css (default) | A viewport (overflow: hidden) clips a full-sheet <img>; each frame updates only transform: translate3d(...) | Most UI sprites — GPU-friendly, no repaint per frame |
| canvas | drawImage onto <canvas> | Custom drawing, filters, or CORS-controlled bitmap access |
CSS renderer (transform + overflow)
Instead of shifting background-position every frame, the CSS renderer:
- Sizes the container to one frame (
width×height) - Places the full sprite sheet inside as an
<img> - Moves the sheet with
translate3dto reveal the active frame
Only transform changes between frames, which keeps work on the compositor and avoids repainting the background layer.
<MasonSprite
src="/sprites/cat-run.webp"
rows={2}
cols={5}
renderer="css" // default
/>Reverse playback
Set reverse to play frames from last → first. On a full sheet, playback starts at the final frame; with playSegment / playAnimation, it starts at the clip's end frame.
<MasonSprite
src="/sprites/cat-run.webp"
rows={2}
cols={5}
reverse
loop={false}
/>
// Or toggle at runtime
ref.current?.stop();
animator.updateOptions({ reverse: true });
animator.play();Controls
Available on SpriteAnimator and via ref / defineExpose / Svelte exports on <MasonSprite>.
| Method | Description |
| --- | --- |
| play() | Start or resume playback |
| pause() | Pause playback |
| stop() | Pause and reset to the clip start (or frame 0) |
| goToFrame(n) | Jump to a frame index |
| playSegment({ start, end, loop? }) | Play a frame range |
| playAnimation(name) | Play a clip from animations |
React hook: useMasonSprite() returns the same controls plus ref and state.
Props
Shared by <MasonSprite> (React / Vue / Svelte) and SpriteAnimator.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| src | string | — | Sprite sheet image URL (PNG, WebP, etc.) |
| rows | number | — | Number of rows in the sheet |
| cols | number | — | Number of columns in the sheet |
| fps | number | 12 | Frames per second |
| loop | boolean | true | Loop the animation |
| reverse | boolean | false | Play frames in reverse (last → first) |
| animations | Record<string, SpriteAnimationClip> | — | Named clips ({ start, end, loop? }) |
| width | number \| string | 128 | Display width — px number or CSS length (rem, %, vw, …) |
| height | number \| string | 128 | Display height — px number or CSS length |
| autoPlay | boolean | true | Start playing on attach |
| renderer | 'css' \| 'canvas' | 'css' | Rendering mode |
| crossOrigin | '' \| 'anonymous' \| 'use-credentials' | CSS: unset; Canvas: 'anonymous' | crossOrigin for the sprite sheet image |
| onLoad | () => void | — | Called when the image loads and the first frame is rendered |
| onError | (error: Event) => void | — | Called when the image fails to load |
| onComplete | () => void | — | Called when a non-looping animation finishes |
| onFrameChange | (frame: number) => void | — | Called on each frame change |
Framework-specific props:
| Framework | Extra props |
| --- | --- |
| React | className, style |
| Vue | class |
| Svelte | class |
Canvas renderer & CORS
The canvas renderer draws the sprite sheet to a <canvas> via drawImage, which requires the image to be CORS-enabled when the sheet is loaded from another origin. By default, crossOrigin is set to 'anonymous' only when renderer is 'canvas'.
The CSS renderer places the sheet in an <img> inside an overflow: hidden viewport and shifts it with transform. It does not set crossOrigin on that image by default, so same-origin sheets without CORS headers still work.
Override explicitly when needed:
new SpriteAnimator({
src: '/sprites/hero.png',
rows: 4,
cols: 5,
renderer: 'canvas',
crossOrigin: 'anonymous', // or '' to omit
});Exports
| Import path | Contents |
| --- | --- |
| mason-sprite | SpriteAnimator, types, utilities |
| mason-sprite/react | MasonSprite, useMasonSprite |
| mason-sprite/vue | MasonSprite |
| mason-sprite/svelte | MasonSprite |
Migration
| v0.1.5 | v0.1.6+ |
| --- | --- |
| Sprite | MasonSprite |
| useSprite | useMasonSprite |
| SpriteProps / SpriteHandle | MasonSpriteProps / MasonSpriteHandle |
Changelog
v0.1.8
No breaking API changes.
- Fix
autoPlayrace when the sprite sheet is not cached: playback now starts after the image loads, from frame 0. - Do not advance frames or fire
onFrameChange/onCompletebefore the image is loaded. srcchanges pause playback, ignore stale loads, and reset to frame 0.crossOriginis optional; default is unset for CSS and'anonymous'for canvas.- CSS renderer uses
transform+overflow+<img>instead ofbackground-positionfor better compositor performance. - Fix reverse playback to start from the last frame (or clip
end); togglingreverseresets to the correct start frame. - React
useMasonSpritekeepsonComplete,onFrameChange,onLoad, andonErrorcallbacks up to date. - Add optional
onLoadandonErrorcallbacks onSpriteAnimationOptions.
License
MIT
