@magic-spells/physics-engine
v1.0.0
Published
A physics-based engine for fun animations.
Downloads
63
Readme
@magic-spells/physics-engine
~1.1 KB gzipped
Spring physics engine for smooth, natural animations. Drives a numeric value from start to end using a spring-damper model, emitting position and progress on every frame.
🔍 Live Demo - See it in action!
Install
npm install @magic-spells/physics-engineimport PhysicsEngine from '@magic-spells/physics-engine';<!-- CDN (UMD) — exposes window.PhysicsEngine -->
<script src="https://unpkg.com/@magic-spells/physics-engine/dist/physics-engine.min.js"></script>Usage
const spring = new PhysicsEngine({ attraction: 0.026, friction: 0.28 });
spring.on('change', ({ position, progress }) => {
element.style.transform = `translateX(${position}px)`;
});
await spring.animateTo(0, 400);Chained animations with initial velocity:
const spring = new PhysicsEngine({ attraction: 0.02, friction: 0.14 });
spring.on('change', ({ position, progress }) => {
element.style.opacity = progress;
element.style.transform = `translateY(${position}px)`;
});
// Animate forward, then back with carry-over velocity
await spring.animateTo(0, 300, 100);
await spring.animateTo(300, 0, -50);API reference
new PhysicsEngine({ attraction?, friction? })
Create a spring engine.
- attraction
number— Spring stiffness. Default0.026. Must be in range (0, 1) exclusive. - friction
number— Velocity damping. Default0.28. Must be in range (0, 1) exclusive.
Throws if either value is outside the valid range.
animateTo(startValue, endValue, velocity?) -> Promise
Animate from startValue to endValue. Returns a Promise that resolves when the spring settles or stop() is called.
- startValue
number— Starting position. - endValue
number— Target position. - velocity
number— Initial velocity. Default0.
If called while already animating, the previous animation is silently stopped and its Promise resolves.
stop()
Halts the current animation. Emits a stop event and resolves the pending Promise.
setAttraction(n)
Update attraction while running or idle. Throws if n is not in (0, 1).
setFriction(n)
Update friction while running or idle. Throws if n is not in (0, 1).
isAnimating
Boolean property. true while an animation is in progress.
Events
| Event | Payload | When |
|-------|---------|------|
| change | { position, progress } | Every animation frame |
| complete | { position, progress } | Spring has settled at the target |
| stop | { position } | stop() was called |
Register and remove listeners with on, off, and removeAllListeners:
function onChange({ position, progress }) { /* ... */ }
spring.on('change', onChange);
spring.off('change', onChange);
spring.removeAllListeners('change'); // remove all for one event
spring.removeAllListeners(); // remove all listenersAll three methods return the instance for chaining.
How it works
Each frame the engine computes a spring force ((target - current) * attraction), adds it to the velocity, damps the velocity by friction, and advances the position. The time delta is normalized to a 16.66ms baseline so the spring behaves consistently across different frame rates. The animation settles when both position and velocity are within 0.01 of the target.
License
MIT
