Frontend Development 29 min read

SpriteJS: A Cross‑Platform Canvas Library for Web Animation, Visualization, and Interaction

SpriteJS is an open‑source, cross‑terminal canvas library from 360 Qiyou that provides a DOM‑like API for drawing shapes, creating sprites, animating with transitions or the Web Animation API, handling textures, vectors, groups, events, and integrating with D3, physics engines and particle systems.

360 Quality & Efficiency
360 Quality & Efficiency
360 Quality & Efficiency
SpriteJS: A Cross‑Platform Canvas Library for Web Animation, Visualization, and Interaction

SpriteJS is an open‑source, cross‑platform canvas library created by the 360 Qiyou team that lets developers draw UI, animations, and visualizations on any canvas environment (browser, mini‑programs, Node) using a DOM‑style API.

Compared with raw Canvas code, SpriteJS reduces boilerplate dramatically. For example, drawing a rounded rectangle with Canvas requires many calls, while the same result is achieved in a few lines with SpriteJS:

const canvas = document.getElementById('paper');
const context = canvas.getContext('2d');
const [x, y, w, h, r] = [200, 200, 200, 200, 50];
context.fillStyle = 'red';
context.beginPath();
context.moveTo(x+r, y);
context.arcTo(x+w, y, x+w, y+h, r);
context.arcTo(x+w, y+h, x, y+h, r);
context.arcTo(x, y+h, x, y, r);
context.arcTo(x, y, x+r, y, r);
context.closePath();
context.fill();
const scene = new spritejs.Scene('#container');
const layer = scene.layer();
const s = new spritejs.Sprite({
  anchor: 0.5,
  bgcolor: 'red',
  pos: [300, 300],
  size: [200, 200],
  borderRadius: 50
});
layer.append(s);

Key features include a document‑object‑model‑like hierarchy, four basic sprite types (Sprite, Path, Label, Group), CSS‑compatible properties, powerful Transition and standard Web Animation API support, texture handling (including sprite sheets), and high‑performance caching.

Animations can be expressed with simple transitions:

const s = new spritejs.Sprite({bgcolor: 'red', anchor: 0.5, pos: [300,300], size: [200,200], borderRadius: 50});
layer.append(s);
s.transition(2.0).attr({bgcolor: 'green'});
// Multiple properties can be animated together
s.transition(2.0).attr({bgcolor: 'green', width: 300});
// Chaining promises enables sequential animations
await s.transition(2.0).attr({bgcolor: 'green'});
await s.transition(1.0).attr({bgcolor: 'yellow'});

Textures are set via the textures attribute, allowing single or multiple images and supporting pre‑loading and sprite‑sheet packing:

const s = new spritejs.Sprite({
  textures: ['https://example.com/image.png'],
  anchor: 0.5,
  pos: [300, 300],
  size: [200, 200],
  scale: 0.5
});
layer.append(s);

Vector graphics are created with the Path type, which can directly use SVG path data:

const p = new spritejs.Path();
p.attr({
  path: {d: 'M280,250A200,200,0,1,1,680,250A200,200,0,1,1,280,250Z'},
  strokeColor: '#033',
  fillColor: '#839',
  lineWidth: 12,
  pos: [100, 50]
});
layer.appendChild(p);

Sprites can be grouped to form composite UI components, and groups inherit transformations and events. An interactive example rotates a group on mouse enter and restores it on mouse leave:

const group = new spritejs.Group();
group.attr({
  anchor: 0.5,
  pos: [610, 600],
  size: [180, 180],
  bgcolor: '#faee35',
  border: [6, '#fdbd2c'],
  borderRadius: 90
});
layer.append(group);
group.on('mouseenter', () => { group.attr({rotate: 360}); });
group.on('mouseleave', () => { group.attr({rotate: 0}); });

Because SpriteJS mimics DOM properties, it integrates smoothly with D3 for data‑driven visualizations:

const s = d3.select(paper).append('fglayer');
const chart = s.selectAll('sprite')
  .data(dataset)
  .enter()
  .append('sprite')
  .attr('x', 450)
  .attr('y', (d,i) => 200 + i*95)
  .attr('width', 0)
  .attr('height', 80)
  .attr('bgcolor', '#ccc')
  .transition()
  .duration(2000)
  .attr('width', d => linear(d))
  .attr('bgcolor', (d,i) => colors[i]);

SpriteJS also offers extensions for physics (Matter.js) and particle systems (Proton). A minimal particle example creates an emitter, sets its rate, initializes radius and life, adds color and alpha behaviours, and runs an animation loop:

const emitter = new Proton.Emitter();
emitter.rate = new Proton.Rate(Proton.getSpan(10,20), 0.1);
emitter.addInitialize(new Proton.Radius(1,12));
emitter.addInitialize(new Proton.Life(2,4));
emitter.addBehaviour(new Proton.Color('#ff0000','random'));
emitter.addBehaviour(new Proton.Alpha(1,0));
layer.appendChild(emitter);
proton.addEmitter(emitter);
function tick(){ requestAnimationFrame(tick); proton.update(); }
tick();

Finally, SpriteJS can be driven by an external clock, enabling seamless combination with other animation libraries such as Curve.js. The example below synchronizes a sprite following a SVG path with Curve.js‑generated motion, while the layer is rendered manually each frame:

const scene = new spritejs.Scene('#curvejs', {resolution:[1540,600]});
const layer = scene.layer('fglayer', {autoRender:false});
const s = new spritejs.Sprite('bird1.png');
s.attr({
  offsetPath: 'M10,80 q100,120 120,20 q140,-50 160,0',
  offsetDistance: 0
});
s.animate([
  {offsetDistance:0},
  {offsetDistance:1}
],{duration:3000,iterations:Infinity});
layer.appendChild(s);
const stage = new curvejs.Stage(layer.canvas);
stage.add(new curvejs.Curve({points:[...], motion: curvejs.motion.rotate}));
function tick(){ stage.update(); layer.draw(false); requestAnimationFrame(tick); }
tick();

SpriteJS’s documentation, GitHub repository, and community groups (WeChat and QQ) provide further resources for developers who want to explore advanced features or contribute to the project.

JavaScriptcanvasData Visualizationweb animationSpriteJS
360 Quality & Efficiency
Written by

360 Quality & Efficiency

360 Quality & Efficiency focuses on seamlessly integrating quality and efficiency in R&D, sharing 360’s internal best practices with industry peers to foster collaboration among Chinese enterprises and drive greater efficiency value.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.