Start here

Introduction

Stew Engine is the animation engine behind Stew Factory. It reads an animation as plain JSON and plays it on SVG, right in the browser.

What it does

You describe what moves as data: a clip, with a track for each thing that moves and keyframes on each track. Stew Engine reads that once, then draws every frame on your SVG, writing only what changed.

The scene below is playing on Stew Engine. The JSON under it is the exact object it plays.

1.2 / 2.4 s
{
  "duration": 2.4,
  "pivots": {
    "hopper": { "x": 144, "y": 214 },
    "star": { "x": 330, "y": 150 }
  },
  "tracks": [
    {
      "targetUid": "hopper",
      "property": "y",
      "keyframes": [
        { "time": 0, "value": 0, "easing": "power2.out" },
        { "time": 0.45, "value": -72, "easing": "power2.in" },
        { "time": 0.9, "value": 0 },
        { "time": 1.2, "value": 0, "easing": "power2.out" },
        { "time": 1.65, "value": -72, "easing": "power2.in" },
        { "time": 2.1, "value": 0 }
      ]
    },
    {
      "targetUid": "hopper",
      "property": "scaleY",
      "keyframes": [
        { "time": 0.9, "value": 1, "easing": "power2.out" },
        { "time": 0.98, "value": 0.78, "easing": "power2.inOut" },
        { "time": 1.14, "value": 1 },
        { "time": 2.1, "value": 1, "easing": "power2.out" },
        { "time": 2.18, "value": 0.78, "easing": "power2.inOut" },
        { "time": 2.34, "value": 1 }
      ]
    },
    {
      "targetUid": "star",
      "property": "rotate",
      "keyframes": [
        { "time": 0, "value": 0, "easing": "back.inOut(1.4)" },
        { "time": 1.2, "value": 144, "easing": "back.inOut(1.4)" },
        { "time": 2.4, "value": 288 }
      ]
    },
    {
      "targetUid": "line",
      "property": "draw",
      "keyframes": [
        { "time": 0.2, "value": 0, "easing": "power2.inOut" },
        { "time": 1.3, "value": 1 }
      ]
    },
    {
      "targetUid": "line",
      "property": "opacity",
      "keyframes": [
        { "time": 1.9, "value": 1, "easing": "power1.in" },
        { "time": 2.3, "value": 0 }
      ]
    }
  ]
}

How it fits together

Three calls take a clip from data to motion. One more puts everything back.

compile(doc)
Reads the clip into a Program: flat lists of numbers, worked out once, before anything plays.
svgDrawer(program, bind)
Draws a moment on the SVG. bind says which elements each target is written to.
createPlayer(program, drawer)
Plays it: play, pause, reverse, seek, glide, speed and repeat, on the page's frame clock.
player.destroy()
Stops, and puts the artwork back exactly as it was before the first frame.

What's inside

The engine is a few small parts, each with one job. It imports nothing: no packages, no app code.

format
The input: Stew animation data, the same JSON Stew Factory saves.
compile
The data into a program of number lists, once.
eval
A program and a moment into a pose. Pure math, no page access.
apply
The pose onto the SVG, and the stage several players share.
path
Path data into curves and back, and distances along a path.
clock
Where time comes from: the page's frame loop, or a clock you step yourself.
player
Ties them together.
start
What starts a clip (load, click, hover, in view, scroll) and rules that play it on an event.
interact
The pointer's actions: follow, run away and drag, on a shape or a single node.

Where it runs today

Everything that moves in Stew Factory plays on Stew Engine: the editor, share pages, video export and every animated download.

The whole engine is about 23 KB compressed. A clip with no pointer actions or rules needs about 17 KB of it.

There is no public package to install yet. These docs show how it works, and every demo on them runs on it.

NextGetting started