springStep
Advance a damped harmonic oscillator by one time step.
springStep(current: number, velocity: number, target: number, stiffness: number, damping: number, mass: number, dt: number): { value: number, velocity: number }
current — Current position of the spring.
velocity — Current velocity.
target — Equilibrium position the spring is pulling toward.
stiffness — Spring constant k. Higher values make the spring snappier (try 170).
damping — Friction coefficient. Higher values reduce bounce (try 26).
mass — Inertia of the object. Higher values make movement slower (try 1).
dt — Time step in seconds. Typically 1/60 for 60 fps.
Returns — An object { value, velocity } with the new position and velocity after the step.
The physics model:
F_spring = -k * (x - target)
F_damping = -c * v
a = (F_spring + F_damping) / m
v' = v + a * dt
x' = x + v' * dt
To interrupt an animation mid-flight, change target -- the physics stays continuous with no discontinuity.
// Spring animation loop
const { springStep, springSettled } = pathRite;
let current = 0;
let velocity = 0;
const target = 100;
const stiffness = 170;
const damping = 26;
const mass = 1;
const precision = 0.01;
function animate() {
const dt = 1 / 60;
const state = springStep(current, velocity, target, stiffness, damping, mass, dt);
current = state.value;
velocity = state.velocity;
// Apply the value (e.g. move an element)
element.style.transform = `translateX(${current}px)`;
if (!springSettled(current, velocity, target, precision)) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
Presets
Common (stiffness, damping, mass) tuples:
| Preset | Stiffness | Damping | Mass | Character |
|---|---|---|---|---|
| Default | 170 | 26 | 1 | Responsive, tiny bounce |
| Gentle | 120 | 14 | 1 | Slow and smooth, no bounce |
| Wobbly | 180 | 12 | 1 | Low damping, lots of bounce |
| Stiff | 210 | 20 | 1 | Fast snap, minimal overshoot |
| Slow | 280 | 60 | 3 | Heavy mass, gentle movement |