Skip to content

Geometry & animation

The foundation packages keep exact shape data and normalized time independent from a renderer.

Geometry

@rougher-stuff/geometry owns the canonical path representation and algorithms shared by Rough.js, Perfect Arrows, and Rough Notation.

sh
pnpm add @rougher-stuff/geometry
ts
import { parseSvgPath, pathBounds, serializeSvgPath, transformPath } from '@rougher-stuff/geometry';

const path = parseSvgPath('m 10 10 q 20 -10 40 0');
const moved = transformPath(path, { a: 1, b: 0, c: 0, d: 1, e: 5, f: 5 });

serializeSvgPath(moved);
pathBounds(moved);

Focused @rougher-stuff/geometry/path, /curve, and /polygon entry points are available. Paths use a flat canonical command stream so producers and renderers do not need an intermediate object tree.

Path metrics support deterministic drawing progress:

ts
const halfway = pointAtLength(path, pathLength(path) / 2);
const [drawn, remaining] = splitPath(path, 0.5);

See the package's geometry specification for coordinate and IR invariants.

Animation

@rougher-stuff/animation provides a framework-neutral controller for normalized progress.

sh
pnpm add @rougher-stuff/animation
ts
import { createAnimation } from '@rougher-stuff/animation';

const animation = createAnimation({
  duration: 800,
  update(progress) {
    render(progress);
  },
});

animation.seek(0.4).play();
await animation.finished;

Controllers support play, pause, reverse, seek, cancellation, completion promises, and event subscriptions. Manual progress does not require browser layout or SVG DOM path metrics.

Released under the MIT License.