@blinn-motion/core is time-based (seconds) and DOM-free. The whole engine hangs off a
single deterministic function; every adapter is a thin painter on top of it.
sample(doc, t)
sample walks the document, samples every track at time t, composes stacked tracks per
property over the base value, and returns a resolved render tree — every transform, RGBA
color and shape vertex is a final number.
t always yields the same tree. That determinism is what makes an
animation time identically on the DOM, on a canvas, and on native views.
Sample
For each track, find the active keyframe segment at
t, ease the local progress, and
interpolate the value.Compose
Combine each track’s value with the base via its
op (set / offset / scale).
Stacked tracks apply in order.Composition
A property can be driven by several tracks. They fold over the base value left to right:setreplaces the running value.offsetadds to it.scalemultiplies it.
The shared clock: Ticker
Adapters don’t run their own timers. They build aTicker — the
shared playback clock — and call sample on each frame. The Ticker owns time, loop, rate
(speed) and the onframe callback, so play / pause / seek / seekFraction behave the
same everywhere.
What the core exports
sample is the headline, but the core is a toolkit of pure helpers — easing solvers, color
interpolation, shape vertex math, paint resolution. See the core API
reference for the full surface.
Core API reference
sample, computeLayer, Ticker, and the easing / color / shape / paint helpers.