The animator's toolbox providing comprehensive animation capabilities including keyframe, spring, and decay animations for numbers, colors, and complex strings
npx @tessl/cli install tessl/npm-popmotion@11.0.0Popmotion is a powerful, low-level JavaScript animation library designed to be the animator's toolbox. It provides comprehensive animation capabilities including keyframe, spring, and decay animations for numbers, colors, and complex strings. Built with TypeScript, it offers over 95% test coverage and maintains a tiny footprint (~4.5kb for the animate function).
npm install popmotionimport { animate, spring, decay, keyframes } from "popmotion";For CommonJS:
const { animate, spring, decay, keyframes } = require("popmotion");import { animate, spring, interpolate, mix } from "popmotion";
// Basic animation
animate({
from: 0,
to: 100,
duration: 1000,
ease: "easeInOut",
onUpdate: (latest) => console.log(latest),
onComplete: () => console.log("Animation complete")
});
// Spring animation
animate({
from: 0,
to: 100,
type: "spring",
stiffness: 400,
damping: 40,
onUpdate: (value) => element.style.left = value + "px"
});
// Color interpolation
const mixColors = interpolate([0, 1], ["#ff0000", "#0000ff"]);
console.log(mixColors(0.5)); // Mixed colorPopmotion is built around several key components:
animate function providing unified interface for all animation typesPrimary animation function with support for spring, decay, and keyframe animations. Includes repeat modes, playback controls, and lifecycle callbacks.
function animate<V = number>(options: AnimationOptions<V>): PlaybackControls;
interface PlaybackControls {
stop: () => void;
}
type AnimationOptions<V> = PlaybackOptions<V> &
(DecayOptions | KeyframeOptions<V> | SpringOptions);
interface PlaybackOptions<V> {
autoplay?: boolean;
driver?: Driver;
elapsed?: number;
from?: V;
repeat?: number;
repeatType?: "loop" | "reverse" | "mirror";
repeatDelay?: number;
type?: "spring" | "decay" | "keyframes";
onUpdate?: (latest: V) => void;
onPlay?: () => void;
onComplete?: () => void;
onRepeat?: () => void;
onStop?: () => void;
}Specialized animation generators for creating different types of motion with precise control over physics parameters and timing.
function spring(options: SpringOptions): Animation<number>;
function decay(options: DecayOptions): Animation<number>;
function keyframes(options: KeyframeOptions): Animation<number | string>;
interface SpringOptions extends PhysicsSpringOptions {
from?: number;
to?: number;
duration?: number;
bounce?: number;
restSpeed?: number;
restDelta?: number;
}
interface DecayOptions {
from?: number;
to?: number;
velocity?: number;
power?: number;
timeConstant?: number;
modifyTarget?: (target: number) => number;
restDelta?: number;
}
interface KeyframeOptions<V = number> {
to: V | V[];
from?: V;
duration?: number;
ease?: Easing | Easing[];
offset?: number[];
}Comprehensive collection of easing functions for natural motion feel, plus utilities for creating custom easing curves and modifying existing ones.
type Easing = (v: number) => number;
// Basic easing functions
const linear: Easing;
const easeIn: Easing;
const easeOut: Easing;
const easeInOut: Easing;
// Custom easing generators
function cubicBezier(mX1: number, mY1: number, mX2: number, mY2: number): Easing;
function steps(steps: number, direction?: Direction): Easing;
function createExpoIn(power: number): Easing;
function createBackIn(power: number): Easing;
function createAnticipate(power: number): Easing;
// Easing modifiers
function mirrorEasing(easing: Easing): Easing;
function reverseEasing(easing: Easing): Easing;Mathematical and interpolation utilities for animation calculations, including value mixing, clamping, geometric operations, type conversion, and attraction effects.
function interpolate<T>(
input: number[],
output: T[],
options?: InterpolateOptions<T>
): (v: number) => T;
function mix(from: number, to: number, progress: number): number;
function clamp(min: number, max: number, v: number): number;
function progress(from: number, to: number, value: number): number;
function attract(constant: number, origin: number, v: number): number;
function attractExpo(constant: number, origin: number, v: number): number;
interface InterpolateOptions<T> {
clamp?: boolean;
ease?: Easing | Easing[];
mixer?: MixerFactory<T>;
}Specialized inertia animation combining decay with spring physics for scroll-like behaviors with boundaries.
function inertia(options: InertiaOptions): PlaybackControls;
interface InertiaOptions extends DecayOptions {
bounceStiffness?: number;
bounceDamping?: number;
min?: number;
max?: number;
restSpeed?: number;
restDelta?: number;
driver?: Driver;
onUpdate?: (v: number) => void;
onComplete?: () => void;
onStop?: () => void;
}interface Animation<V> {
next: (t: number) => { value: V; done: boolean };
flipTarget: () => void;
}
interface AnimationState<V> {
value: V;
done: boolean;
}
type Driver = (update: (timestamp: number) => void) => DriverControls;
interface DriverControls {
start: () => void;
stop: () => void;
}
type Point2D = {
x: number;
y: number;
};
type Point3D = Point2D & {
z: number;
};
type Point = Point2D | Point3D;
interface PhysicsSpringOptions {
velocity?: number;
stiffness?: number;
damping?: number;
mass?: number;
}
type MixerFactory<T> = (from: T, to: T) => (v: number) => T;