# How to Use Spring Physics for Natural Animations in Anime.js

> Create natural physics based animations with Anime.js spring easing. Learn to configure bounce, stiffness, and duration for realistic motion.

- Repository: [Julian Garnier/anime](https://github.com/juliangarnier/anime)
- Tags: tutorial
- Published: 2026-03-04

---

**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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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:

```javascript
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()`:

```javascript
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:

```javascript
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:

```javascript
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`](https://github.com/juliangarnier/anime/blob/main/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:

```javascript
import { draggable } from 'animejs';

draggable({
  target: '.card',
  // Spring physics automatically applied on release
});

```

## Practical Code Examples

### Example 1: Simple Bouncy Translation

```javascript
anime({
  targets: '#box',
  translateX: 300,
  easing: anime.spring({ bounce: 0.5, duration: 1500 })
});

```

### Example 2: Overdamped Rotation with Callback

```javascript
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

```javascript
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`](https://github.com/juliangarnier/anime/blob/main/src/easings/spring/index.js) and demonstrated in [`examples/auto-layout/todo-list/index.js`](https://github.com/juliangarnier/anime/blob/main/examples/auto-layout/todo-list/index.js) and [`examples/easings-visualizer/index.js`](https://github.com/juliangarnier/anime/blob/main/examples/easings-visualizer/index.js).

## Summary

- Anime.js implements spring physics through the `Spring` class in [`src/easings/spring/index.js`](https://github.com/juliangarnier/anime/blob/main/src/easings/spring/index.js), providing a physics-based alternative to traditional easing functions.
- The `spring()` factory accepts `bounce`, `duration`, `mass`, `stiffness`, `damping`, and `velocity` parameters, using the `calculateSDFromBD()` algorithm to derive physical constants.
- The animation engine in [`src/animation/animation.js`](https://github.com/juliangarnier/anime/blob/main/src/animation/animation.js) automatically uses the computed `settlingDuration` as 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.js`](https://github.com/juliangarnier/anime/blob/main/src/draggable/draggable.js) and 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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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`](https://github.com/juliangarnier/anime/blob/main/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.