The animator's toolbox providing comprehensive animation capabilities including keyframe, spring, and decay animations for numbers, colors, and complex strings
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The core animation system provides a unified interface for creating different types of animations with comprehensive playback controls and lifecycle management.
The primary animation function that detects animation type from options and provides unified control interface.
/**
* Creates an animation from the provided options
* @param options - Animation configuration including type, timing, and callbacks
* @returns PlaybackControls interface for stopping the animation
*/
function animate<V = number>(options: AnimationOptions<V>): PlaybackControls;
interface PlaybackControls {
/** Stop the animation immediately */
stop: () => void;
}
type AnimationOptions<V> = PlaybackOptions<V> &
(DecayOptions | KeyframeOptions<V> | SpringOptions);
interface PlaybackOptions<V> {
/** Whether to start animation immediately (default: true) */
autoplay?: boolean;
/** Custom driver for animation timing (default: framesync) */
driver?: Driver;
/** Starting elapsed time in milliseconds */
elapsed?: number;
/** Starting value for animation */
from?: V;
/** Number of times to repeat animation (0 = no repeat) */
repeat?: number;
/** How to handle repeats: loop, reverse, or mirror */
repeatType?: "loop" | "reverse" | "mirror";
/** Delay between repeats in milliseconds */
repeatDelay?: number;
/** Animation type hint (auto-detected if not provided) */
type?: "spring" | "decay" | "keyframes";
/** Called with latest value on each frame */
onUpdate?: (latest: V) => void;
/** Called when animation starts playing */
onPlay?: () => void;
/** Called when animation completes (not on stop) */
onComplete?: () => void;
/** Called each time animation repeats */
onRepeat?: () => void;
/** Called when animation is stopped */
onStop?: () => void;
}Usage Examples:
import { animate } from "popmotion";
// Basic keyframe animation
animate({
from: 0,
to: 100,
duration: 1000,
onUpdate: (value) => element.style.opacity = value / 100
});
// Spring animation with physics
animate({
from: 0,
to: 100,
type: "spring",
stiffness: 400,
damping: 40,
onUpdate: (value) => element.style.left = value + "px"
});
// Repeating animation with callbacks
const controls = animate({
from: 0,
to: 360,
duration: 2000,
repeat: Infinity,
repeatType: "loop",
onUpdate: (degrees) => element.style.transform = `rotate(${degrees}deg)`,
onComplete: () => console.log("Animation complete"),
onRepeat: () => console.log("Animation repeating")
});
// Stop animation later
setTimeout(() => controls.stop(), 5000);The driver system allows custom timing mechanisms for animations, with framesync as the default.
/**
* Animation driver interface for custom timing control
* @param update - Function to call with elapsed time
* @returns Controls for starting and stopping the driver
*/
type Driver = (update: (timestamp: number) => void) => DriverControls;
interface DriverControls {
/** Start the driver timing loop */
start: () => void;
/** Stop the driver timing loop */
stop: () => void;
}Usage Examples:
import { animate } from "popmotion";
// Custom driver using setInterval
const intervalDriver = (update) => {
let intervalId;
let startTime = Date.now();
return {
start: () => {
intervalId = setInterval(() => {
update(Date.now() - startTime);
}, 16); // ~60fps
},
stop: () => clearInterval(intervalId)
};
};
animate({
from: 0,
to: 100,
duration: 1000,
driver: intervalDriver,
onUpdate: (value) => console.log(value)
});The animation state interface defines the structure returned by animation generators.
interface Animation<V> {
/**
* Get the next animation state for given elapsed time
* @param t - Elapsed time in milliseconds
* @returns Current value and completion status
*/
next: (t: number) => AnimationState<V>;
/** Flip the target for mirror-type animations */
flipTarget: () => void;
}
interface AnimationState<V> {
/** Current animated value */
value: V;
/** Whether animation has completed */
done: boolean;
}Restarts animation from beginning on each repeat.
animate({
from: 0,
to: 100,
duration: 1000,
repeat: 3,
repeatType: "loop" // 0→100, 0→100, 0→100, 0→100
});Alternates direction on each repeat.
animate({
from: 0,
to: 100,
duration: 1000,
repeat: 3,
repeatType: "reverse" // 0→100, 100→0, 0→100, 100→0
});Flips the target value on each repeat while maintaining direction.
animate({
from: 0,
to: 100,
duration: 1000,
repeat: 3,
repeatType: "mirror" // 0→100, 100→0, 0→100, 100→0
});Install with Tessl CLI
npx tessl i tessl/npm-popmotion