How to Use Spring Physics for Natural Animations in Anime.js
Anime.js implements spring-based easing through a dedicated Spring class that models physical mass-spring-damper systems, allowing developers to create natural, physics-based animations by configuring bounce, stiffness, and duration parameters.
Anime.js, the lightweight JavaScript animation library maintained by Julian Garnier, provides first-class support for spring physics through its spring() easing function. This feature enables you to move beyond traditional easing curves and create animations that behave like real physical objects. Understanding how to use spring physics for natural animations allows you to build interactions that feel responsive and organic, from bouncy UI elements to smooth drag-and-release behaviors.
Understanding Spring Physics Architecture
The spring physics system centers around the Spring class defined in src/easings/spring/index.js. This class encapsulates the physics solver and exposes an easing function that integrates seamlessly with the animation engine.
The Spring Class Core
The Spring class implements a physical solver handling underdamped, critically damped, and overdamped scenarios. It computes a realistic settlingDuration—the time required for the spring to come to rest—which the animation engine uses as the default animation length unless explicitly overridden by a user-provided duration.
The factory function spring() (lines 49-53 in src/easings/spring/index.js) creates Spring instances for public API consumption, enabling the ergonomic syntax anime({ easing: spring() }). This is re-exported through src/easings/index.js to make it available at anime.easings.spring.
How the Physics Solver Works
The solver uses an algorithm borrowed from Apple SwiftUI to bridge perceived animation timing with physical parameters. During initialization, the constructor normalizes user-provided values—bounce, duration, mass, stiffness, damping, and velocity—clamping them to safe ranges using maxSpringParamValue.
If you supply bounce or duration, the calculateSDFromBD() method derives the underlying stiffness (s) and damping (d) values that match the requested behavior. The compute() method then calculates the natural frequency (w0), damping ratio (zeta), and auxiliary values (wd, b).
The solver iteratively steps forward using a timeStep of 0.02 seconds until the spring settles within restThreshold for maxRestSteps consecutive iterations or exceeds maxIterations. The resulting settlingDuration determines the animation length, as implemented in src/animation/animation.js.
Implementing Spring Physics for Natural Animations
Basic Spring Usage
To apply spring physics, pass the spring() easing function to any Anime.js animation configuration:
import anime from 'animejs';
anime({
targets: '.box',
translateX: 250,
easing: anime.spring(),
});
Customizing Physical Parameters
Fine-tune the physics by passing a configuration object to anime.spring():
anime({
targets: '.ball',
translateY: 300,
easing: anime.spring({
bounce: 0.4, // Range: -1 to 1 (positive = bouncy/underdamped)
duration: 1200, // Perceived animation length in milliseconds
mass: 1,
stiffness: 150,
damping: 20,
velocity: 0,
onComplete: (anim) => console.log('Spring settled!'),
}),
});
When bounce is positive, the spring is underdamped and oscillates. Negative values create overdamped springs that settle slowly without bouncing.
Advanced Spring Configuration
Reusable Spring Instances
Create a Spring instance once and reuse it across multiple animations to maintain consistent physics throughout your application:
const mySpring = anime.spring({ bounce: 0.3, duration: 800 });
anime({
targets: '#elem1',
rotate: 360,
easing: mySpring,
});
anime({
targets: '#elem2',
scale: 2,
easing: mySpring,
});
Dynamic Parameter Modification
A Spring instance exposes getters and setters that trigger automatic recomputation of dependent physical parameters:
const s = anime.spring({ bounce: 0.2, duration: 600 });
s.bounce = 0.6; // Automatically recomputes stiffness and damping
s.stiffness = 200; // Automatically recomputes bounce and duration
Spring Integration with Draggable Elements
The draggable module in src/draggable/draggable.js demonstrates real-world spring usage for inertia after drag release. If you omit an explicit easing, the module automatically creates a default spring for the release animation:
import { draggable } from 'animejs';
draggable({
target: '.card',
// Spring physics automatically applied on release
});
Practical Code Examples
Example 1: Simple Bouncy Translation
anime({
targets: '#box',
translateX: 300,
easing: anime.spring({ bounce: 0.5, duration: 1500 })
});
Example 2: Overdamped Rotation with Callback
const springEasing = anime.spring({
bounce: -0.3, // Overdamped: slow settle, no oscillation
duration: 2000,
onComplete: (anim) => alert('Animation finished!')
});
anime({
targets: '#circle',
rotate: 720,
easing: springEasing
});
Example 3: Synchronized Spring Across Multiple Elements
const sharedSpring = anime.spring({ bounce: 0.4, duration: 1000 });
anime({
targets: '.dot1',
translateY: -200,
easing: sharedSpring
});
anime({
targets: '.dot2',
translateY: -200,
delay: 200,
easing: sharedSpring
});
These examples rely on the underlying Spring class documented in src/easings/spring/index.js and demonstrated in examples/auto-layout/todo-list/index.js and examples/easings-visualizer/index.js.
Summary
- Anime.js implements spring physics through the
Springclass insrc/easings/spring/index.js, providing a physics-based alternative to traditional easing functions. - The
spring()factory acceptsbounce,duration,mass,stiffness,damping, andvelocityparameters, using thecalculateSDFromBD()algorithm to derive physical constants. - The animation engine in
src/animation/animation.jsautomatically uses the computedsettlingDurationas the animation length unless explicitly overridden. - Spring instances can be reused across multiple animations and modified dynamically; property setters automatically recompute the underlying physics.
- Real-world applications include drag-and-release interactions in
src/draggable/draggable.jsand layout animations in the examples directory.
Frequently Asked Questions
What is the difference between bounce and duration in Anime.js springs?
The bounce parameter controls the damping ratio with a range of -1 to 1, where positive values create underdamped bouncy springs and negative values create overdamped slow settles. The duration parameter represents the perceived animation length in milliseconds. When you provide either value, Anime.js uses the calculateSDFromBD() algorithm—mirroring Apple SwiftUI's implementation—to compute the underlying physical stiffness and damping parameters that produce the requested visual behavior.
How does Anime.js calculate the actual animation duration for spring easings?
According to the source code in src/easings/spring/index.js, the compute() method iteratively solves the spring physics using a fixed timeStep of 0.02 seconds until the velocity remains below the restThreshold for maxRestSteps consecutive iterations. This produces a settlingDuration representing the precise time required for the physical system to come to rest. The animation engine in src/animation/animation.js then uses this value as the default animation duration, ensuring the physics complete naturally.
Can I use the same spring configuration for multiple animations?
Yes. The anime.spring() factory returns a Spring instance that functions as a reusable easing function. You can store this instance in a constant and pass it to the easing property of multiple anime() calls, ensuring all elements follow identical physical parameters. This pattern is demonstrated in examples/auto-layout/todo-list/index.js where shared springs create cohesive motion across list items.
What happens if I modify spring parameters after creating the instance?
The Spring class implements getters and setters that trigger automatic recomputation of the physics model. When you modify properties like bounce, stiffness, or duration on an existing instance, the class automatically recalculates the dependent parameters—such as w0, zeta, wd, and b—and updates the easing curve without requiring you to instantiate a new spring object.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →