animaly

Animation, computed in columns.

A data-oriented animation engine for the web. Springs, tweens, keyframes and inertia, written to the DOM once per frame.

  • Springs solved in closed form
  • Velocity kept when you retarget
  • One transform write per element per frame
  • Under 128 bytes allocated per frame
  • Compositor path for transforms and opacity

One engine. Every driver.

Every animated value is a row in a set of Float64Array columns. Springs, tweens, keyframes and inertia step in one loop over the rows that move.

  1. 01Write one call

    Pass elements or a selector, the values to reach and how to get there. Transforms combine into one transform string per element.

    import { animate, stagger } from "@animaly/dom";
    
    animate(".card", { x: 120, opacity: 1 }, {
      type: "spring",
      stiffness: 300,
      damping: 20,
    });
    
    animate(".dot", { scale: [1, 1.4, 1] }, {
      duration: 0.6,
      delay: stagger(0.05, { from: "center" }),
    });
  2. 02Retarget mid-flight

    Call animate again before the first spring settles. The new spring starts from the current position and keeps the current velocity.

    animate(".box", { x: 400 }, { type: "spring" });
    
    // Later, while it is still moving:
    // the new spring starts from the current
    // position and keeps the current velocity.
    animate(".box", { x: 0 }, { type: "spring" });
    Click the track, then click again before the ball settles.Velocity 0 px/s

See it in motion.

Every demo on this page runs on animaly, live in your browser.

Springs. Forty dots, staggered by row and column, each solved in closed form.
Ripples. 216 dots on the JS path, each delayed by its distance from the center.
Inertia. Four throws at 120 to 1,400 px/s. The fast ones bounce off the edge and settle.

Measured against motion.

motion 13.4.6's time divided by animaly's, headless Chromium, engines interleaved over 5 repetitions. Higher is better for animaly.

Scenario1,000 elements10,000 elements
Main-thread time per frame, tween1.30x1.31x
Main-thread time per frame, spring1.41x1.35x
Script time per frame, tween2.3x2.7x
Script time per frame, spring2.5x3.2x
Starting all animations1.75x1.23x
Retargeting all animations3.0x3.3x

One call in your code.
One write per frame.

Version 0.1 is on npm. The API can still change before 1.0.

pnpm add @animaly/dom