How to Use Custom Easing Functions in Anime.js: A Complete Guide to Cubic Bézier, Spring Physics, and More
Anime.js supports custom easing functions through cubic Bézier curves, step-wise jumps, piecewise linear interpolation, parameterized Penner formulas, spring physics, and raw mathematical functions, all exported from the main module and processed by the parseEase parser in src/easings/eases/parser.js.
Anime.js provides a powerful animation engine that extends far beyond standard easing presets. When you need precise control over acceleration curves for specific motion design requirements, the library offers multiple factory methods to define custom easing functions. This guide examines the implementation details and usage patterns for each approach based on the Anime.js source code.
How the Easing Parser Works
Before an easing function reaches the animation loop, Anime.js processes it through parseEase in src/easings/eases/parser.js. This parser normalizes any easing input into a standard function signature (t: number) => number:
- Function detection: If the value is already a function, it passes through unchanged.
- String parsing: Named easings like
"outQuad"are looked up in the cachedeasesLookupsregistry. - Factory invocation: Strings containing parentheses (e.g.,
"cubicBezier(0.4,0,0.2,1)") trigger the corresponding factory function with parsed arguments. - Normalization: The final output is always a normalized easing function receiving time
t ∈ [0,1].
The parser caches string-based lookups to avoid recomputing named easings on every animation frame.
Creating Custom Easing Functions
Anime.js exports six primary factory methods from src/index.js for constructing custom easings. Each generates a normalized easing function compatible with the ease property.
Cubic Bézier Curves with cubicBezier()
The cubicBezier(x1, y1, x2, y2) factory in src/easings/cubic-bezier/index.js generates CSS-compatible Bézier curves. The implementation solves the cubic equation to map input time t to output value y using the four control points.
import { animate, cubicBezier } from 'animejs';
animate('.box', {
translateX: 300,
duration: 1200,
// Material Design "fast-out-slow-in" curve
ease: cubicBezier(0.4, 0, 0.2, 1),
});
Step-wise Animation with steps()
For discrete, frame-like motion, the steps(count, fromStart?) factory in src/easings/steps/index.js creates a staircase function. The fromStart boolean (default false) determines whether jumps occur at the start or end of each interval.
import { animate, steps } from 'animejs';
animate('.dot', {
opacity: [0, 1],
duration: 800,
// 5 discrete jumps, starting at the beginning of each step
ease: steps(5, true),
});
Piecewise Linear Interpolation with linear()
The linear(...points) factory in src/easings/linear/index.js constructs easing functions from arbitrary control points. Accept numbers or percentage strings ('25% 75%') to define non-uniform acceleration curves.
import { animate, linear } from 'animejs';
animate('.bar', {
width: ['0%', '100%'],
duration: 1500,
// Hold at 0.25 until 30% of time, then jump to 0.75 at 70%
ease: linear(0, '0.25 30%', '0.75 70%', 1),
});
Parameterized Penner Easings with eases()
The eases object in src/easings/eases/parser.js (lines 44-48) exposes factories for Penner equations with custom parameters. Use eases.in(p), eases.out(p), eases.inOut(p), and eases.outIn(p) for power-based curves, or specialized methods for Back and Elastic effects.
import { animate, eases } from 'animejs';
// Custom cubic-in curve (power = 3)
animate('.ball', {
scale: [0, 1],
duration: 600,
ease: eases.in(3),
});
// Elastic easing with custom amplitude and period
animate('.spring', {
translateY: [0, -200],
duration: 1200,
ease: eases.outElastic(1.5, 0.5),
});
The parser implements these at lines 33 (power functions) and 78-86 (Elastic definitions).
Spring Physics with spring()
For physically-based motion, the spring(options) factory in src/easings/spring/index.js (lines 49-94) creates easings derived from mass-spring-damper systems. The solver automatically calculates duration based on physical parameters rather than using a fixed duration.
import { animate, spring } from 'animejs';
animate('.panel', {
rotate: [0, 360],
// Heavy mass with low stiffness creates a long, overshooting motion
ease: spring({ mass: 5, stiffness: 30, damping: 12 }),
});
Raw Mathematical Functions
Any function conforming to (t: number) => number can be passed directly to the ease property. Anime.js uses this function verbatim without parsing, bypassing the parseEase logic entirely.
import { animate } from 'animejs';
animate('.dot', {
opacity: [0, 1],
duration: 500,
// Simple quadratic ease-in
ease: t => t * t,
});
Summary
- Cubic Bézier curves generated by
cubicBezier()insrc/easings/cubic-bezier/index.jsprovide CSS-compatible timing functions using four control points. - Step-wise easings created with
steps()insrc/easings/steps/index.jsproduce discrete frame-like motion with configurable jump points. - Piecewise linear interpolation via
linear()insrc/easings/linear/index.jsallows arbitrary control point definitions using numbers or percentage strings. - Parameterized Penner equations exposed through the
easesobject insrc/easings/eases/parser.jssupport custom power curves, Back overshoot, and Elastic amplitude/period adjustments. - Spring physics simulated by
spring()insrc/easings/spring/index.jsgenerate physically-based motion using mass, stiffness, and damping parameters with automatically calculated duration. - Raw functions bypass the parser entirely, accepting any
(t) => numberimplementation directly. - All factories are exported from
src/index.jsand normalized throughparseEaseinsrc/easings/eases/parser.js.
Frequently Asked Questions
How do I import custom easing factories in Anime.js?
All custom easing factories—including cubicBezier, steps, linear, spring, and the eases object—are exported from the main entry point. Import them directly alongside the animate function using import { animate, cubicBezier, spring } from 'animejs';.
Can I use CSS cubic-bezier values directly in Anime.js?
Yes. The cubicBezier(x1, y1, x2, y2) factory in src/easings/cubic-bezier/index.js accepts the same four numeric values used in CSS cubic-bezier() timing functions. The implementation solves the cubic Bézier equation mathematically to ensure identical acceleration curves across browsers.
What is the difference between steps() and linear() easing?
The steps(count, fromStart) function in src/easings/steps/index.js creates a staircase effect that jumps between discrete values without interpolation, similar to CSS steps(). In contrast, linear(...points) in src/easings/linear/index.js interpolates linearly between specified control points, creating continuous straight-line segments rather than jumps.
How does the spring() function calculate animation duration?
Unlike other easings that map time to progress within a fixed duration, the spring(options) factory in src/easings/spring/index.js (lines 49-94) derives duration automatically from physical parameters. The Spring class simulates a mass-spring-damper system and computes when the motion settles below a rest threshold, returning an easing function with an implicit duration calculated from the physics simulation rather than a predefined millisecond value.
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 →