animejs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAnime.js — Skill Reference
Anime.js — 技能参考文档
Lightweight, modular, high-performance JavaScript animation engine. Current version: 4.0.0 | Official docs: https://animejs.com/documentation
轻量级、模块化、高性能的JavaScript动画引擎。 当前版本:4.0.0 | 官方文档:https://animejs.com/documentation
Activation Contract
激活场景
Use this skill when:
- Building web animations (CSS properties, transforms, colors) in vanilla JS or any framework
- Creating animation sequences with timelines
- Implementing scroll-triggered animations
- Animating SVG elements (morphing, drawing, motion paths)
- Text animations (split, scramble effects)
- Interactive animations (draggable, animatable)
Works with: Vanilla JS, React, Vue, Svelte, Next.js, Nuxt, or any DOM-based project.
Do NOT use this skill for:
- Complex physics simulations (use Matter.js or similar)
- Canvas/WebGL animations (use Three.js or Pixi.js)
- Video/audio sync (use native Web APIs)
当你需要以下场景时使用本技能:
- 在原生JS或任意框架中构建Web动画(CSS属性、变换、颜色)
- 创建带时间线的动画序列
- 实现滚动触发式动画
- 为SVG元素添加动画(变形、描边、运动路径)
- 文本动画(拆分、打乱效果)
- 交互式动画(可拖拽、可动画)
兼容框架:Vanilla JS、React、Vue、Svelte、Next.js、Nuxt或任何基于DOM的项目。
请勿在以下场景使用本技能:
- 复杂物理模拟(使用Matter.js或类似库)
- Canvas/WebGL动画(使用Three.js或Pixi.js)
- 视频/音频同步(使用原生Web API)
Decision Gates
决策指引
| Need | Use |
|---|---|
| Simple one-shot animation | |
| Timers and time control | |
| Orchestrate multiple animations | |
| Real-time updates (mouse, scroll) | |
| Drag-and-drop with physics | |
| Layout changes (FLIP technique) | |
| Responsive animations | |
| Scroll-triggered animations | |
| SVG morphing | |
| SVG line drawing | |
| SVG path following | |
| Text character/word animation | |
| Text scramble effect | |
| Staggered animations | |
| Physics springs | |
| High-performance transforms | |
| Global engine configuration | |
| 需求 | 使用方法 |
|---|---|
| 简单单次动画 | |
| 计时器与时间控制 | |
| 编排多个动画 | |
| 实时更新(鼠标、滚动) | |
| 带物理效果的拖拽 | |
| 布局变化(FLIP技术) | |
| 响应式动画 | |
| 滚动触发动画 | |
| SVG变形 | |
| SVG描边动画 | |
| SVG路径跟随 | |
| 文本字符/单词动画 | |
| 文本打乱效果 | |
| 交错动画 | |
| 物理弹簧效果 | |
| 高性能变换 | |
| 全局引擎配置 | |
Hard Rules
硬性规则
- Import only what you need — Use modular imports to keep bundle size small (~24KB total)
- Use transforms over positioning — Transform properties (x, y, scale, rotate) are GPU-accelerated
- Prefer timelines over nested callbacks — is more readable than callback chains
createTimeline() - Use WAAPI for transforms/opacity only — Use JS engine for colors, scroll sync, and callbacks
- Clean up after yourself — Call or
revert()on animations when components unmountcancel() - Avoid animating layout properties — Animate and
transform, notopacity/widthdirectlyheight
- 仅导入所需模块 — 使用模块化导入以减小包体积(总大小约24KB)
- 优先使用变换而非定位 — 变换属性(x、y、scale、rotate)由GPU加速
- 优先使用时间线而非嵌套回调 — 比回调链更具可读性
createTimeline() - 仅对变换/透明度使用WAAPI — 颜色、滚动同步和回调使用JS引擎
- 及时清理资源 — 组件卸载时调用动画的或
revert()方法cancel() - 避免为布局属性添加动画 — 为和
transform添加动画,而非直接动画opacity/widthheight
Output Contract
输出约定
When this skill is invoked, return:
- Relevant code snippets for the requested animation pattern
- Module imports needed for the feature
- Performance considerations if applicable
- Cleanup recommendations
当调用本技能时,返回:
- 对应动画模式的相关代码片段
- 功能所需的模块导入语句
- 性能注意事项(如适用)
- 清理建议
Installation
安装
bash
npm install animejsjs
// ES Modules (bundler: Vite, esbuild, etc.)
import { animate, createTimeline, stagger } from 'animejs';
// CommonJS
const { animate } = require('animejs');
// CDN — ES Module
import { animate } from 'https://esm.sh/animejs';
// or JsDelivr
import { animate } from 'https://cdn.jsdelivr.net/npm/animejs/+esm';
// CDN — UMD (script tag)
// <script src="https://cdn.jsdelivr.net/npm/animejs/dist/bundles/anime.umd.min.js"></script>
// const { animate } = anime;bash
npm install animejsjs
// ES Modules(打包工具:Vite、esbuild等)
import { animate, createTimeline, stagger } from 'animejs';
// CommonJS
const { animate } = require('animejs');
// CDN — ES Module
import { animate } from 'https://esm.sh/animejs';
// 或JsDelivr
import { animate } from 'https://cdn.jsdelivr.net/npm/animejs/+esm';
// CDN — UMD(script标签)
// <script src="https://cdn.jsdelivr.net/npm/animejs/dist/bundles/anime.umd.min.js"></script>
// const { animate } = anime;Available distribution files
可用的分发文件
| File | Type |
|---|---|
| ES modules entry point |
| CommonJS entry point |
| Minified ES bundle |
| Minified UMD bundle |
| 文件 | 类型 |
|---|---|
| ES模块入口 |
| CommonJS入口 |
| 压缩后的ES包 |
| 压缩后的UMD包 |
Bundle size (modular)
模块化包体积
| Module | Size |
|---|---|
| Timer | 5.60 KB |
| Animation | +5.20 KB |
| Timeline | +0.55 KB |
| Animatable | +0.40 KB |
| Draggable | +6.41 KB |
| Scroll | +4.30 KB |
| Scope | +0.22 KB |
| SVG | 0.35 KB |
| Stagger | +0.48 KB |
| Spring | 0.52 KB |
| WAAPI | 3.50 KB |
| Total | ~24.50 KB |
| 模块 | 大小 |
|---|---|
| Timer | 5.60 KB |
| Animation | +5.20 KB |
| Timeline | +0.55 KB |
| Animatable | +0.40 KB |
| Draggable | +6.41 KB |
| Scroll | +4.30 KB |
| Scope | +0.22 KB |
| SVG | 0.35 KB |
| Stagger | +0.48 KB |
| Spring | 0.52 KB |
| WAAPI | 3.50 KB |
| 总计 | ~24.50 KB |
Module imports
模块导入
Only import what you need to keep the bundle small:
js
import {
animate, // Main animation function
createTimer, // Timer without animated properties
createTimeline, // Animation sequencer
createAnimatable, // Real-time animatable properties
createDraggable, // Draggable elements
createScope, // Responsive scope
createLayout, // Automatic layout animations
onScroll, // Scroll Observer
stagger, // Staggering utility
createSpring, // Physics spring
waapi, // Enhanced Web Animation API
utils, // Math and DOM utilities
// SVG
morphTo,
createDrawable,
createMotionPath,
// Text
splitText,
scrambleText,
// Engine
engine,
} from 'animejs';仅导入所需模块以减小包体积:
js
import {
animate, // 主动画函数
createTimer, // 无动画属性的计时器
createTimeline, // 动画序列编排器
createAnimatable, // 实时可动画属性
createDraggable, // 可拖拽元素
createScope, // 响应式作用域
createLayout, // 自动布局动画
onScroll, // 滚动观察者
stagger, // 交错动画工具
createSpring, // 物理弹簧效果
waapi, // 增强版Web动画API
utils, // 数学与DOM工具
// SVG相关
morphTo,
createDrawable,
createMotionPath,
// 文本相关
splitText,
scrambleText,
// 引擎
engine,
} from 'animejs';1. animate() — Main animation function
1. animate() — 主动画函数
js
animate(targets, parameters);js
animate(targets, parameters);Targets
目标元素
js
// CSS Selector
animate('.box', { x: 100 });
// DOM Element
animate(document.querySelector('.box'), { x: 100 });
// NodeList / Array of elements
animate(document.querySelectorAll('.box'), { x: 100 });
// JavaScript Object
const obj = { value: 0 };
animate(obj, { value: 100, onUpdate: () => console.log(obj.value) });
// Mixed array
animate(['.box', myElement, myObject], { opacity: 0 });js
// CSS选择器
animate('.box', { x: 100 });
// DOM元素
animate(document.querySelector('.box'), { x: 100 });
// NodeList / 元素数组
animate(document.querySelectorAll('.box'), { x: 100 });
// JavaScript对象
const obj = { value: 0 };
animate(obj, { value: 100, onUpdate: () => console.log(obj.value) });
// 混合数组
animate(['.box', myElement, myObject], { opacity: 0 });Animatable properties
可动画属性
js
// CSS Properties
animate('.el', {
width: '200px',
backgroundColor: '#ff0000',
opacity: 0.5,
borderRadius: '50%',
});
// CSS Transforms (individual, no conflicts)
animate('.el', {
x: 100, // translateX
y: 50, // translateY
z: 0, // translateZ
rotate: 90, // rotateZ (degrees by default)
rotateX: 45,
rotateY: 45,
scale: 1.5,
scaleX: 2,
scaleY: 0.5,
skew: 15,
skewX: 10,
skewY: 10,
});
// CSS Variables
animate('.el', { '--my-color': '#ff0000' });
// HTML Attributes
animate('input[type=range]', { value: 50 });
// SVG Attributes
animate('circle', { r: 50, cx: 100, cy: 100 });
// JS Object properties
const data = { count: 0 };
animate(data, { count: 100 });js
// CSS属性
animate('.el', {
width: '200px',
backgroundColor: '#ff0000',
opacity: 0.5,
borderRadius: '50%',
});
// CSS变换(独立设置,无冲突)
animate('.el', {
x: 100, // translateX
y: 50, // translateY
z: 0, // translateZ
rotate: 90, // rotateZ(默认单位为度)
rotateX: 45,
rotateY: 45,
scale: 1.5,
scaleX: 2,
scaleY: 0.5,
skew: 15,
skewX: 10,
skewY: 10,
});
// CSS变量
animate('.el', { '--my-color': '#ff0000' });
// HTML属性
animate('input[type=range]', { value: 50 });
// SVG属性
animate('circle', { r: 50, cx: 100, cy: 100 });
// JS对象属性
const data = { count: 0 };
animate(data, { count: 100 });Tween value types
补间值类型
js
// Numerical
animate('.el', { x: 100 });
// With unit (automatic conversion)
animate('.el', { width: '50%' }); // converts from px
animate('.el', { x: '10rem' });
// Relative (JS only)
animate('.el', { x: '+=50' }); // add 50
animate('.el', { x: '-=50' }); // subtract 50
animate('.el', { x: '*=2' }); // multiply by 2
// Color
animate('.el', { backgroundColor: 'rgb(255, 0, 0)' });
animate('.el', { backgroundColor: '#ff0000' });
animate('.el', { backgroundColor: 'hsl(0, 100%, 50%)' });
// Color function (WAAPI)
animate('.el', { color: 'oklch(70% 0.2 120)' });
// CSS variable as value
animate('.el', { x: 'var(--offset)' });
// Function-based (per element)
animate('.el', {
x: (el, index, total) => index * 50,
delay: (el, index) => index * 100,
});js
// 数值
animate('.el', { x: 100 });
// 带单位(自动转换)
animate('.el', { width: '50%' }); // 从px转换
animate('.el', { x: '10rem' });
// 相对值(仅JS)
animate('.el', { x: '+=50' }); // 增加50
animate('.el', { x: '-=50' }); // 减少50
animate('.el', { x: '*=2' }); // 乘以2
// 颜色
animate('.el', { backgroundColor: 'rgb(255, 0, 0)' });
animate('.el', { backgroundColor: '#ff0000' });
animate('.el', { backgroundColor: 'hsl(0, 100%, 50%)' });
// 颜色函数(WAAPI)
animate('.el', { color: 'oklch(70% 0.2 120)' });
// CSS变量作为值
animate('.el', { x: 'var(--offset)' });
// 基于函数的取值(按元素)
animate('.el', {
x: (el, index, total) => index * 50,
delay: (el, index) => index * 100,
});Tween parameters (per property)
补间参数(按属性)
js
animate('.el', {
x: {
to: 200,
from: 0, // forced initial value
delay: 200,
duration: 800,
ease: 'inOutExpo',
composition: 'add', // 'replace' | 'add' | 'blend'
modifier: v => Math.round(v),
},
});js
animate('.el', {
x: {
to: 200,
from: 0, // 强制初始值
delay: 200,
duration: 800,
ease: 'inOutExpo',
composition: 'add', // 'replace' | 'add' | 'blend'
modifier: v => Math.round(v),
},
});Keyframes
关键帧
js
// Tween values keyframes (array of values)
animate('.el', {
x: [0, 50, 100, 50, 0],
});
// Tween parameters keyframes
animate('.el', {
x: [
{ to: 100, duration: 500, ease: 'outExpo' },
{ to: 0, duration: 500, ease: 'inExpo' },
],
});
// Duration-based keyframes (JS only)
animate('.el', {
keyframes: [
{ x: 100, duration: 400 },
{ y: 50, duration: 300 },
{ rotate: 90, duration: 500 },
],
});
// Percentage-based keyframes (JS only)
animate('.el', {
keyframes: {
'0%': { x: 0, opacity: 1 },
'50%': { x: 100, opacity: 0.5 },
'100%': { x: 200, opacity: 1 },
},
});js
// 补间值关键帧(值数组)
animate('.el', {
x: [0, 50, 100, 50, 0],
});
// 补间参数关键帧
animate('.el', {
x: [
{ to: 100, duration: 500, ease: 'outExpo' },
{ to: 0, duration: 500, ease: 'inExpo' },
],
});
// 基于时长的关键帧(仅JS)
animate('.el', {
keyframes: [
{ x: 100, duration: 400 },
{ y: 50, duration: 300 },
{ rotate: 90, duration: 500 },
],
});
// 基于百分比的关键帧(仅JS)
animate('.el', {
keyframes: {
'0%': { x: 0, opacity: 1 },
'50%': { x: 100, opacity: 0.5 },
'100%': { x: 200, opacity: 1 },
},
});Playback settings
播放设置
js
animate('.el', {
x: 100,
delay: 500, // delay before starting (ms)
duration: 1000, // duration (ms)
loop: true, // true = infinite, number = repetitions
loopDelay: 200, // pause between loops (JS only)
alternate: true, // reverses direction on each loop
reversed: false, // plays in reverse
autoplay: true, // starts automatically
frameRate: 60, // max FPS (JS only)
playbackRate: 1, // speed (0.5 = half speed)
playbackEase: 'linear', // global easing for the animation (JS only)
persist: false, // keeps styles after completion (WAAPI only)
});js
animate('.el', {
x: 100,
delay: 500, // 开始前延迟(毫秒)
duration: 1000, // 时长(毫秒)
loop: true, // true=无限循环,数字=重复次数
loopDelay: 200, // 循环间隔(仅JS)
alternate: true, // 每次循环反向播放
reversed: false, // 反向播放
autoplay: true, // 自动开始
frameRate: 60, // 最大帧率(仅JS)
playbackRate: 1, // 播放速度(0.5=半速)
playbackEase: 'linear', // 动画全局缓动(仅JS)
persist: false, // 完成后保留样式(仅WAAPI)
});Callbacks
回调函数
js
animate('.el', {
x: 100,
onBegin: (anim) => console.log('started'), // JS only
onComplete: (anim) => console.log('complete'),
onBeforeUpdate: (anim) => {}, // JS only
onUpdate: (anim) => console.log(anim.progress), // JS only
onRender: (anim) => {}, // JS only
onLoop: (anim) => {}, // JS only
onPause: (anim) => {}, // JS only
}).then((anim) => console.log('promise resolved'));js
animate('.el', {
x: 100,
onBegin: (anim) => console.log('已启动'), // 仅JS
onComplete: (anim) => console.log('已完成'),
onBeforeUpdate: (anim) => {}, // 仅JS
onUpdate: (anim) => console.log(anim.progress), // 仅JS
onRender: (anim) => {}, // 仅JS
onLoop: (anim) => {}, // 仅JS
onPause: (anim) => {}, // 仅JS
}).then((anim) => console.log('Promise已解决'));Animation methods
动画方法
js
const anim = animate('.el', { x: 100, autoplay: false });
anim.play(); // play
anim.pause(); // pause
anim.resume(); // resume
anim.reverse(); // reverse direction
anim.restart(); // restart from the beginning
anim.alternate(); // alternate direction
anim.complete(); // jump to end
anim.cancel(); // cancel without reverting
anim.revert(); // cancel and restore original values
anim.reset(); // reset to initial state (JS only)
anim.seek(500); // jump to time in ms
anim.stretch(2000); // stretch total duration (JS only)
anim.refresh(); // recompute values (JS only)js
const anim = animate('.el', { x: 100, autoplay: false });
anim.play(); // 播放
anim.pause(); // 暂停
anim.resume(); // 恢复
anim.reverse(); // 反向
anim.restart(); // 重启
anim.alternate(); // 切换方向
anim.complete(); // 跳至结束
anim.cancel(); // 取消且不还原
anim.revert(); // 取消并还原初始值
anim.reset(); // 重置为初始状态(仅JS)
anim.seek(500); // 跳至指定时间(毫秒)
anim.stretch(2000); // 拉伸总时长(仅JS)
anim.refresh(); // 重新计算值(仅JS)Animation properties
动画属性
js
anim.duration // total duration (ms)
anim.currentTime // current time (ms)
anim.progress // progress 0-1
anim.paused // boolean
anim.began // boolean
anim.completed // boolean
anim.reversed // boolean
anim.targets // array of targetsjs
anim.duration // 总时长(毫秒)
anim.currentTime // 当前时间(毫秒)
anim.progress // 进度0-1
anim.paused // 布尔值
anim.began // 布尔值
anim.completed // 布尔值
anim.reversed // 布尔值
anim.targets // 目标元素数组2. createTimer() — Timer
2. createTimer() — 计时器
Pure timer without animated properties, useful for orchestrating timing logic.
js
import { createTimer } from 'animejs';
const timer = createTimer({
duration: 2000,
loop: true,
onUpdate: (t) => console.log(t.currentTime),
onComplete: (t) => console.log('done'),
});Supports the same playback settings, callbacks, and methods as .
animate()纯计时器,无动画属性,适用于编排时间逻辑。
js
import { createTimer } from 'animejs';
const timer = createTimer({
duration: 2000,
loop: true,
onUpdate: (t) => console.log(t.currentTime),
onComplete: (t) => console.log('完成'),
});支持与相同的播放设置、回调函数和方法。
animate()3. createTimeline() — Timeline
3. createTimeline() — 时间线
Orchestrates animation sequences with precise time control.
js
import { createTimeline } from 'animejs';
const tl = createTimeline({
loop: true,
defaults: { duration: 500, ease: 'outExpo' }, // defaults for all animations
});
// Add animations (chained in sequence by default)
tl.add('.box', { x: 100 })
.add('.circle', { y: 100 })
.add('.text', { opacity: 0 });精确控制动画序列的编排。
js
import { createTimeline } from 'animejs';
const tl = createTimeline({
loop: true,
defaults: { duration: 500, ease: 'outExpo' }, // 所有动画的默认设置
});
// 添加动画(默认按顺序链式执行)
tl.add('.box', { x: 100 })
.add('.circle', { y: 100 })
.add('.text', { opacity: 0 });Time positions
时间位置
js
tl.add('.el', { x: 100 }) // after the previous
.add('.el', { y: 50 }, 500) // absolute: at 500ms from start
.add('.el', { scale: 2 }, '+=200') // relative: 200ms AFTER the previous ends
.add('.el', { rotate: 90 }, '-=100') // relative: 100ms BEFORE the previous ends
.add('.el', { opacity: 0 }, '<') // at the same time as the previous
.add('.el', { opacity: 1 }, '<100') // 100ms after the start of the previous
.label('myLabel') // label at current time
.add('.el', { x: 0 }, 'myLabel'); // position by labeljs
tl.add('.el', { x: 100 }) // 在上一个动画之后
.add('.el', { y: 50 }, 500) // 绝对时间:从开始起500毫秒处
.add('.el', { scale: 2 }, '+=200') // 相对时间:上一个动画结束后200毫秒
.add('.el', { rotate: 90 }, '-=100') // 相对时间:上一个动画结束前100毫秒
.add('.el', { opacity: 0 }, '<') // 与上一个动画同时开始
.add('.el', { opacity: 1 }, '<100') // 上一个动画开始后100毫秒
.label('myLabel') // 在当前时间添加标签
.add('.el', { x: 0 }, 'myLabel'); // 按标签位置添加Timeline methods
时间线方法
js
tl.add(targets, params, position) // add animation
.set(targets, params, position) // set values instantly
.sync(animation, position) // sync external animation
.call(fn, position) // call function at a specific time
.label('name', position) // add label
.remove(targets) // remove animations for targets
.init() // initialize without playing
// Playback (same as animate)
tl.play() .pause() .resume() .reverse()
.restart() .alternate() .complete()
.cancel() .revert() .reset()
.seek(ms) .stretch(ms) .refresh()js
tl.add(targets, params, position) // 添加动画
.set(targets, params, position) // 立即设置值
.sync(animation, position) // 同步外部动画
.call(fn, position) // 在指定时间调用函数
.label('name', position) // 添加标签
.remove(targets) // 移除目标元素的动画
.init() // 初始化但不播放
// 播放控制(与animate()相同)
tl.play() .pause() .resume() .reverse()
.restart() .alternate() .complete()
.cancel() .revert() .reset()
.seek(ms) .stretch(ms) .refresh()4. createAnimatable() — Animatable
4. createAnimatable() — 可动画对象
Imperatively animate properties in real time (ideal for mouse interactions, smooth scroll, etc.).
js
import { createAnimatable } from 'animejs';
const box = createAnimatable('.box', {
x: { duration: 500, ease: 'outSpring' },
y: { duration: 500, ease: 'outSpring' },
scale: { duration: 300 },
// unit: 'px', // default unit
// modifier: v => v, // global modifier
});
// Setter: animates to the new value
box.x(200);
box.y(100);
box.scale(1.5);
// Getter: returns current value
console.log(box.x()); // null if not yet set
// Revert
box.revert();实时命令式动画属性(适用于鼠标交互、平滑滚动等场景)。
js
import { createAnimatable } from 'animejs';
const box = createAnimatable('.box', {
x: { duration: 500, ease: 'outSpring' },
y: { duration: 500, ease: 'outSpring' },
scale: { duration: 300 },
// unit: 'px', // 默认单位
// modifier: v => v, // 全局修饰器
});
// 设置器:动画到新值
box.x(200);
box.y(100);
box.scale(1.5);
// 获取器:返回当前值
console.log(box.x()); // 未设置时返回null
// 还原
box.revert();5. createDraggable() — Draggable
5. createDraggable() — 可拖拽对象
Makes elements draggable with spring physics and snapping.
js
import { createDraggable, createSpring } from 'animejs';
const draggable = createDraggable('.card', {
// Axis constraints
x: true, // allow drag on X
y: false, // lock Y axis
// x: { mapTo: anotherElement }, // map position to another element
// Container and bounds
container: '.wrapper', // selector, element, 'window', or 'parent'
containerPadding: 20, // inner padding of the container
containerFriction: 0.8, // friction when dragged outside the container
// Snap
snap: 50, // number, array, or function
// snap: [0, 100, 200, 300],
// snap: (val) => Math.round(val / 50) * 50,
// Release physics
releaseEase: createSpring({ stiffness: 200, damping: 15 }),
releaseMass: 1,
releaseStiffness: 200,
releaseDamping: 15,
releaseContainerFriction: 0.85,
// Velocity
velocityMultiplier: 1,
minVelocity: 0,
maxVelocity: Infinity,
dragSpeed: 1,
dragThreshold: 0, // min pixels to start dragging
// Auto-scroll
scrollThreshold: 20,
scrollSpeed: 10,
// Cursor
cursor: 'grab', // CSS cursor on hover
trigger: '.handle', // element that triggers the drag
// Callbacks
onGrab: (d) => {},
onDrag: (d) => {},
onUpdate: (d) => {},
onRelease: (d) => {},
onSnap: (d) => {},
onSettle: (d) => {},
onResize: (d) => {},
onAfterResize: (d) => {},
});
// Methods
draggable.enable();
draggable.disable();
draggable.setX(100);
draggable.setY(50);
draggable.animateInView();
draggable.scrollInView();
draggable.stop();
draggable.reset();
draggable.revert();
draggable.refresh();为元素添加拖拽功能,支持弹簧物理和吸附效果。
js
import { createDraggable, createSpring } from 'animejs';
const draggable = createDraggable('.card', {
// 轴约束
x: true, // 允许X轴拖拽
y: false, // 锁定Y轴
// x: { mapTo: anotherElement }, // 将位置映射到另一个元素
// 容器与边界
container: '.wrapper', // 选择器、元素、'window'或'parent'
containerPadding: 20, // 容器内边距
containerFriction: 0.8, // 拖拽出容器时的摩擦力
// 吸附
snap: 50, // 数字、数组或函数
// snap: [0, 100, 200, 300],
// snap: (val) => Math.round(val / 50) * 50,
// 释放物理效果
releaseEase: createSpring({ stiffness: 200, damping: 15 }),
releaseMass: 1,
releaseStiffness: 200,
releaseDamping: 15,
releaseContainerFriction: 0.85,
// 速度
velocityMultiplier: 1,
minVelocity: 0,
maxVelocity: Infinity,
dragSpeed: 1,
dragThreshold: 0, // 触发拖拽的最小像素
// 自动滚动
scrollThreshold: 20,
scrollSpeed: 10,
// 光标
cursor: 'grab', // hover时的CSS光标
trigger: '.handle', // 触发拖拽的元素
// 回调函数
onGrab: (d) => {},
onDrag: (d) => {},
onUpdate: (d) => {},
onRelease: (d) => {},
onSnap: (d) => {},
onSettle: (d) => {},
onResize: (d) => {},
onAfterResize: (d) => {},
});
// 方法
draggable.enable();
draggable.disable();
draggable.setX(100);
draggable.setY(50);
draggable.animateInView();
draggable.scrollInView();
draggable.stop();
draggable.reset();
draggable.revert();
draggable.refresh();6. createLayout() — Layout Animations
6. createLayout() — 布局动画
Automatically animates layout changes using the FLIP technique (First, Last, Invert, Play).
js
import { createLayout } from 'animejs';
const layout = createLayout('.container', {
children: true, // animate container children
duration: 600,
ease: 'outExpo',
properties: ['width', 'height', 'transform', 'opacity'],
// Enter/exit states
enterFrom: { opacity: 0, scale: 0.5 },
leaveTo: { opacity: 0, scale: 0.5 },
swapAt: 0.5, // swap point (0-1)
});
// Typical usage
layout.record(); // capture current positions
// ... make DOM changes ...
layout.animate(); // animate from previous position to new one
// Or combined:
layout.update(() => {
// DOM changes here
});
layout.revert(); // revert animation使用FLIP技术(First, Last, Invert, Play)自动为布局变化添加动画。
js
import { createLayout } from 'animejs';
const layout = createLayout('.container', {
children: true, // 为容器子元素添加动画
duration: 600,
ease: 'outExpo',
properties: ['width', 'height', 'transform', 'opacity'],
// 进入/退出状态
enterFrom: { opacity: 0, scale: 0.5 },
leaveTo: { opacity: 0, scale: 0.5 },
swapAt: 0.5, // 交换点(0-1)
});
// 典型用法
layout.record(); // 记录当前位置
// ... 进行DOM变更 ...
layout.animate(); // 从之前的位置动画到新位置
// 或合并使用:
layout.update(() => {
// 此处进行DOM变更
});
layout.revert(); // 还原动画Using data-layout-id
使用data-layout-id
html
<!-- Elements with the same layout-id are tracked across containers -->
<div data-layout-id="card-1" class="container-a">Card</div>
<!-- After moving to the other container: -->
<div data-layout-id="card-1" class="container-b">Card</div>html
<!-- 拥有相同layout-id的元素会在容器间被追踪 -->
<div data-layout-id="card-1" class="container-a">卡片</div>
<!-- 移动到另一个容器后: -->
<div data-layout-id="card-1" class="container-b">卡片</div>Layout use cases
布局动画适用场景
js
// CSS display property animation
// DOM reorder animation
// Enter / Exit animations
// Modal dialog animations
// Swap parent animations (element moves between parent containers)js
// CSS display属性动画
// DOM重排动画
// 进入/退出动画
// 模态框动画
// 跨父容器动画(元素在父容器间移动)7. createScope() — Scope
7. createScope() — 作用域
Groups animations with shared defaults and media query support for responsive animations.
js
import { createScope } from 'animejs';
const scope = createScope({
root: '.my-component', // root element (selector context)
defaults: { duration: 600, ease: 'outExpo' },
mediaQueries: {
mobile: '(max-width: 768px)',
portrait: '(orientation: portrait)',
dark: '(prefers-color-scheme: dark)',
},
});
// add() re-runs whenever a media query changes
scope.add(({ matches, root }) => {
const isMobile = matches.mobile;
createTimeline()
.add('.box', {
x: isMobile ? 0 : 200,
y: isMobile ? 100 : 0,
});
// Optionally return a cleanup function
return () => {};
});
// addOnce() runs only once (does not re-run on media query change)
scope.addOnce(() => {
animate('.logo', { opacity: 1, delay: 500 });
});
scope.revert(); // cleans up all animations in the scope
scope.refresh(); // re-runs all constructors
scope.keepTime(); // preserves time when refreshing将动画分组,共享默认设置并支持媒体查询,实现响应式动画。
js
import { createScope } from 'animejs';
const scope = createScope({
root: '.my-component', // 根元素(选择器上下文)
defaults: { duration: 600, ease: 'outExpo' },
mediaQueries: {
mobile: '(max-width: 768px)',
portrait: '(orientation: portrait)',
dark: '(prefers-color-scheme: dark)',
},
});
// add()会在媒体查询变化时重新执行
scope.add(({ matches, root }) => {
const isMobile = matches.mobile;
createTimeline()
.add('.box', {
x: isMobile ? 0 : 200,
y: isMobile ? 100 : 0,
});
// 可选返回清理函数
return () => {};
});
// addOnce()仅执行一次(媒体查询变化时不重新执行)
scope.addOnce(() => {
animate('.logo', { opacity: 1, delay: 500 });
});
scope.revert(); // 清理作用域内的所有动画
scope.refresh(); // 重新执行所有构造函数
scope.keepTime(); // 刷新时保留时间8. onScroll() — Scroll Observer
8. onScroll() — 滚动观察者
Synchronizes and triggers animations based on scroll position.
js
import { animate, onScroll } from 'animejs';
// As the autoplay value of an animation
animate('.el', {
x: 200,
autoplay: onScroll(),
});
// Full configuration
animate('.section', {
opacity: [0, 1],
autoplay: onScroll({
container: window, // scroll container
target: '.section', // observed element (defaults to animation target)
axis: 'y', // 'x' | 'y'
debug: false, // shows visual markers
// Thresholds: when the element enters/leaves
// Shorthand: 'top bottom' = when top of element hits bottom of viewport
enter: 'bottom top', // enters when scrolling down
leave: 'top bottom', // leaves when scrolling
// Numeric values (0-1 relative to viewport)
enter: 0.5, // at the viewport midpoint
// Relative values
enter: '50% 100%', // 50% of the element at 100% of the container
repeat: true, // repeats the animation each time
// Synchronisation modes
sync: true, // syncs progress with scroll
sync: 'play', // calls play() on enter
sync: 'restart', // calls restart() on enter
sync: 'resume', // calls resume() on enter
// Callbacks
onEnter: (obs) => {},
onEnterForward: (obs) => {},
onEnterBackward: (obs) => {},
onLeave: (obs) => {},
onLeaveForward: (obs) => {},
onLeaveBackward: (obs) => {},
onUpdate: (obs) => {},
onSyncComplete: (obs) => {},
onResize: (obs) => {},
}),
});根据滚动位置同步并触发动画。
js
import { animate, onScroll } from 'animejs';
// 作为动画的autoplay值
animate('.el', {
x: 200,
autoplay: onScroll(),
});
// 完整配置
animate('.section', {
opacity: [0, 1],
autoplay: onScroll({
container: window, // 滚动容器
target: '.section', // 观察元素(默认是动画目标)
axis: 'y', // 'x' | 'y'
debug: false, // 显示视觉标记
// 阈值:元素进入/离开的条件
// 简写:'top bottom' = 元素顶部碰到视口底部时
enter: 'bottom top', // 向下滚动时进入
leave: 'top bottom', // 滚动时离开
// 数值(0-1,相对于视口)
enter: 0.5, // 在视口中点
// 相对值
enter: '50% 100%', // 元素50%进入容器100%位置
repeat: true, // 每次进入都重复动画
// 同步模式
sync: true, // 进度与滚动同步
sync: 'play', // 进入时调用play()
sync: 'restart', // 进入时调用restart()
sync: 'resume', // 进入时调用resume()
// 回调函数
onEnter: (obs) => {},
onEnterForward: (obs) => {},
onEnterBackward: (obs) => {},
onLeave: (obs) => {},
onLeaveForward: (obs) => {},
onLeaveBackward: (obs) => {},
onUpdate: (obs) => {},
onSyncComplete: (obs) => {},
onResize: (obs) => {},
}),
});ScrollObserver methods
ScrollObserver方法
js
const obs = onScroll({ target: '.el' });
obs.link(anim); // link an animation
obs.refresh(); // recompute thresholds
obs.revert(); // destroy the observerjs
const obs = onScroll({ target: '.el' });
obs.link(anim); // 关联动画
obs.refresh(); // 重新计算阈值
obs.revert(); // 销毁观察者9. SVG — Utilities
9. SVG — 工具
js
import { animate, morphTo, createDrawable, createMotionPath } from 'animejs';
// morphTo — SVG shape morphing
animate('#shape-a', {
d: morphTo('#shape-b'), // morph to another element's path
duration: 1000,
ease: 'inOutQuad',
});
// createDrawable — SVG line drawing animation
const drawable = createDrawable('path');
animate(drawable, {
draw: '0 1', // from start to end of stroke
// draw: ['0 0', '0 1', '1 1'], // keyframes
duration: 1500,
ease: 'inOutSine',
});
// draw: [start, end] where start and end are 0-1
// createMotionPath — Follow an SVG path
animate('.car', {
...createMotionPath('.road'), // spreads x, y, rotate properties
duration: 3000,
ease: 'linear',
});js
import { animate, morphTo, createDrawable, createMotionPath } from 'animejs';
// morphTo — SVG形状变形
animate('#shape-a', {
d: morphTo('#shape-b'), // 变形为另一个元素的路径
duration: 1000,
ease: 'inOutQuad',
});
// createDrawable — SVG描边动画
const drawable = createDrawable('path');
animate(drawable, {
draw: '0 1', // 从描边起点到终点
// draw: ['0 0', '0 1', '1 1'], // 关键帧
duration: 1500,
ease: 'inOutSine',
});
// draw: [start, end] 其中start和end为0-1
// createMotionPath — 跟随SVG路径
animate('.car', {
...createMotionPath('.road'), // 展开x、y、rotate属性
duration: 3000,
ease: 'linear',
});10. Text — Text utilities
10. Text — 文本工具
splitText()
splitText()
Splits text into lines, words, and/or characters to animate them individually.
js
import { splitText, animate, stagger } from 'animejs';
const splitter = splitText('.heading', {
lines: true,
words: true,
chars: true,
includeSpaces: false,
debug: false,
accessible: true, // aria-hidden on spans, aria-label on parent
});
// Animate characters
animate(splitter.chars, {
opacity: [0, 1],
y: [20, 0],
delay: stagger(30),
duration: 600,
ease: 'outExpo',
});
// Animate words
animate(splitter.words, {
scale: [0.8, 1],
delay: stagger(50),
});
// Available properties
splitter.lines // array of line elements
splitter.words // array of word elements
splitter.chars // array of character elements
// Methods
splitter.addEffect((el) => {
// custom effect logic
});
splitter.refresh(); // recompute after resize
splitter.revert(); // restore original HTML将文本拆分为行、单词和/或字符,以便单独为其添加动画。
js
import { splitText, animate, stagger } from 'animejs';
const splitter = splitText('.heading', {
lines: true,
words: true,
chars: true,
includeSpaces: false,
debug: false,
accessible: true, // 为span添加aria-hidden,为父元素添加aria-label
});
// 为字符添加动画
animate(splitter.chars, {
opacity: [0, 1],
y: [20, 0],
delay: stagger(30),
duration: 600,
ease: 'outExpo',
});
// 为单词添加动画
animate(splitter.words, {
scale: [0.8, 1],
delay: stagger(50),
});
// 可用属性
splitter.lines // 行元素数组
splitter.words // 单词元素数组
splitter.chars // 字符元素数组
// 方法
splitter.addEffect((el) => {
// 自定义效果逻辑
});
splitter.refresh(); // 调整后重新计算
splitter.revert(); // 恢复原始HTMLSplit parameters
拆分参数
js
splitText('.el', {
lines: { class: 'my-line', wrap: '.wrapper', clone: false },
words: { class: 'my-word' },
chars: { class: 'my-char' },
});js
splitText('.el', {
lines: { class: 'my-line', wrap: '.wrapper', clone: false },
words: { class: 'my-word' },
chars: { class: 'my-char' },
});scrambleText() (NEW)
scrambleText()(新增)
Scramble effect that randomly shuffles characters while revealing the target text.
js
import { animate, scrambleText } from 'animejs';
animate('.heading', {
...scrambleText({
text: 'New text', // destination text
chars: 'abcdefghijklmnopqrstuvwxyz', // scramble character set
override: false, // overwrite current text
ease: 'linear',
cursor: true, // show cursor at the end
revealRate: 0.5,
revealDelay: 0,
settleRate: 0.5,
settleDuration: 1000,
delay: 0,
duration: 1000,
perturbation: 1,
from: 'start', // 'start' | 'end' | 'center' | number
reversed: false,
seed: 0,
onChange: (val, target) => {},
}),
});打乱效果:在显示目标文本时随机打乱字符。
js
import { animate, scrambleText } from 'animejs';
animate('.heading', {
...scrambleText({
text: 'New text', // 目标文本
chars: 'abcdefghijklmnopqrstuvwxyz', // 打乱字符集
override: false, // 是否覆盖当前文本
ease: 'linear',
cursor: true, // 在末尾显示光标
revealRate: 0.5,
revealDelay: 0,
settleRate: 0.5,
settleDuration: 1000,
delay: 0,
duration: 1000,
perturbation: 1,
from: 'start', // 'start' | 'end' | 'center' | 数字
reversed: false,
seed: 0,
onChange: (val, target) => {},
}),
});11. stagger() — Staggering
11. stagger() — 交错动画
Creates staggered delays or values across multiple elements.
js
import { animate, stagger } from 'animejs';
// Time staggering (delay per index)
animate('.dots', {
y: -20,
delay: stagger(100), // 0, 100, 200, 300...
delay: stagger(100, { start: 200 }), // 200, 300, 400...
delay: stagger(100, { from: 'center' }), // from the center outward
delay: stagger(100, { from: 2 }), // from index 2
delay: stagger(100, { reversed: true }), // reversed
delay: stagger(100, { ease: 'inOutQuad' }), // with easing
});
// Value staggering (range between first and last element)
animate('.dots', {
scale: stagger([0.5, 1.5]), // from 0.5 to 1.5
x: stagger(['-100px', '100px']),
});
// 2D Grid staggering
animate('.grid-item', {
scale: stagger(0.1, {
grid: [10, 10], // columns x rows
from: 'center', // origin point
axis: 'x', // 'x' | 'y' | undefined (diagonal)
}),
});
// Timeline staggering (time positions)
createTimeline()
.add('.el', { y: -10 }, stagger(50)); // each element offset by +50ms
// Full parameters
stagger(value, {
start: 0, // start value or time
from: 'first', // 'first'|'center'|'last'|'edges'|index|[col,row]
reversed: false,
ease: 'linear',
grid: [cols, rows],
axis: 'x', // 'x'|'y'
modifier: (v) => v,
use: 'delay', // property to stagger
total: undefined, // forced total element count
});为多个元素创建交错延迟或值。
js
import { animate, stagger } from 'animejs';
// 时间交错(按索引延迟)
animate('.dots', {
y: -20,
delay: stagger(100), // 0, 100, 200, 300...
delay: stagger(100, { start: 200 }), // 200, 300, 400...
delay: stagger(100, { from: 'center' }), // 从中心向外
delay: stagger(100, { from: 2 }), // 从索引2开始
delay: stagger(100, { reversed: true }), // 反向
delay: stagger(100, { ease: 'inOutQuad' }), // 带缓动
});
// 值交错(第一个到最后一个元素的范围)
animate('.dots', {
scale: stagger([0.5, 1.5]), // 从0.5到1.5
x: stagger(['-100px', '100px']),
});
// 2D网格交错
animate('.grid-item', {
scale: stagger(0.1, {
grid: [10, 10], // 列数 x 行数
from: 'center', // 起始点
axis: 'x', // 'x' | 'y' | undefined(对角线)
}),
});
// 时间线交错(时间位置)
createTimeline()
.add('.el', { y: -10 }, stagger(50)); // 每个元素偏移+50毫秒
// 完整参数
stagger(value, {
start: 0, // 起始值或时间
from: 'first', // 'first'|'center'|'last'|'edges'|索引|[列,行]
reversed: false,
ease: 'linear',
grid: [cols, rows],
axis: 'x', // 'x'|'y'
modifier: (v) => v,
use: 'delay', // 要交错的属性
total: undefined, // 强制元素总数
});12. Easings — Easing functions
12. Easings — 缓动函数
Built-in eases
内置缓动
js
// Syntax: 'type(exponent)'
'linear'
'ease' // CSS alias
// In / Out / InOut — 3 forms:
'in(n)' // inSine ~ in(1.675)
'out(n)'
'inOut(n)'
// Predefined aliases (shortcuts)
'inSine' 'outSine' 'inOutSine'
'inQuad' 'outQuad' 'inOutQuad'
'inCubic' 'outCubic' 'inOutCubic'
'inQuart' 'outQuart' 'inOutQuart'
'inQuint' 'outQuint' 'inOutQuint'
'inExpo' 'outExpo' 'inOutExpo'
'inCirc' 'outCirc' 'inOutCirc'
'inBack' 'outBack' 'inOutBack'
'inBounce' 'outBounce' 'inOutBounce'
'inElastic' 'outElastic' 'inOutElastic'js
// 语法:'type(exponent)'
'linear'
'ease' // CSS别名
// In / Out / InOut — 三种形式:
'in(n)' // inSine ~ in(1.675)
'out(n)'
'inOut(n)'
// 预定义别名(快捷方式)
'inSine' 'outSine' 'inOutSine'
'inQuad' 'outQuad' 'inOutQuad'
'inCubic' 'outCubic' 'inOutCubic'
'inQuart' 'outQuart' 'inOutQuart'
'inQuint' 'outQuint' 'inOutQuint'
'inExpo' 'outExpo' 'inOutExpo'
'inCirc' 'outCirc' 'inOutCirc'
'inBack' 'outBack' 'inOutBack'
'inBounce' 'outBounce' 'inOutBounce'
'inElastic' 'outElastic' 'inOutElastic'Cubic Bezier
三次贝塞尔曲线
js
// cubicBezier(x1, y1, x2, y2)
ease: 'cubicBezier(0.25, 0.1, 0.25, 1.0)'
// or using createCubicBezier:
import { createCubicBezier } from 'animejs';
ease: createCubicBezier(0.25, 0.1, 0.25, 1.0)js
// cubicBezier(x1, y1, x2, y2)
ease: 'cubicBezier(0.25, 0.1, 0.25, 1.0)'
// 或使用createCubicBezier:
import { createCubicBezier } from 'animejs';
ease: createCubicBezier(0.25, 0.1, 0.25, 1.0)Linear (multi-point)
线性(多点)
js
// linear([p1, p2, p3, ...]) — values between 0 and 1
ease: 'linear(0, 0.5, 1)'
ease: 'linear(0, 0.2 25%, 0.8 75%, 1)'js
// linear([p1, p2, p3, ...]) — 值在0和1之间
ease: 'linear(0, 0.5, 1)'
ease: 'linear(0, 0.2 25%, 0.8 75%, 1)'Steps
阶梯函数
js
// steps(n, direction)
ease: 'steps(5)'
ease: 'steps(5, start)' // 'start'|'end'|'both'|'none'js
// steps(n, direction)
ease: 'steps(5)'
ease: 'steps(5, start)' // 'start'|'end'|'both'|'none'Irregular (Custom)
不规则(自定义)
js
import { createIrregular } from 'animejs';
ease: createIrregular(/* seed, amplitude, frequency */);js
import { createIrregular } from 'animejs';
ease: createIrregular(/* seed, amplitude, frequency */);Spring
弹簧
js
import { createSpring } from 'animejs';
ease: createSpring({
mass: 1, // object mass
stiffness: 100, // spring stiffness
damping: 10, // damping coefficient
velocity: 0, // initial velocity
});
// or shorthand string
ease: 'spring(mass, stiffness, damping, velocity)'
ease: 'spring(1, 100, 10, 0)'
// outSpring (damped, comes to rest)
ease: 'outSpring'
ease: 'outSpring(stiffness, damping)'js
import { createSpring } from 'animejs';
ease: createSpring({
mass: 1, // 对象质量
stiffness: 100, // 弹簧刚度
damping: 10, // 阻尼系数
velocity: 0, // 初始速度
});
// 或简写字符串
ease: 'spring(mass, stiffness, damping, velocity)'
ease: 'spring(1, 100, 10, 0)'
// outSpring(阻尼,最终静止)
ease: 'outSpring'
ease: 'outSpring(stiffness, damping)'13. Utilities
13. Utilities — 工具函数
js
import {
$, get, set, cleanInlineStyles, remove, sync, keepTime,
random, createSeededRandom, randomPick, shuffle,
round, clamp, snap, wrap, mapRange, lerp, damp,
roundPad, padStart, padEnd, degToRad, radToDeg,
utils,
} from 'animejs';
// DOM
$('.selector') // querySelectorAll -> array
get(target, 'x') // get the current value of a property
set(target, { x: 100 }) // set value instantly
cleanInlineStyles(target) // remove inline styles left by animations
remove(target) // remove target from all active animations
sync(fn) // run fn on the next engine frame
keepTime(timer) // preserve timer time on revert
// Numbers
random(0, 100) // random number between min and max
random(0, 100, 2) // with decimal places
createSeededRandom(seed) // reproducible random generator -> fn()
randomPick([a, b, c]) // pick a random element from an array
shuffle([1, 2, 3, 4]) // shuffle array in place (mutates)
round(3.1415, 2) // -> 3.14
clamp(value, min, max) // clamp value to range
snap(value, increment) // round to nearest increment
snap(value, [0,50,100]) // round to nearest value in array
wrap(value, min, max) // wrap value within range (modulo)
mapRange(value, inMin, inMax, outMin, outMax) // remap a value between ranges
lerp(a, b, t) // linear interpolation
damp(current, target, lambda, dt) // smooth damp (frame-rate independent)
roundPad(value, decimals) // round with trailing zeros: 1.5 -> "1.50"
padStart(str, length, char) // pad left
padEnd(str, length, char) // pad right
degToRad(180) // -> Math.PI
radToDeg(Math.PI) // -> 180
// Chain-able utilities
utils(value)
.round(2)
.clamp(0, 100)
.mapRange(0, 100, 0, 1)
.get() // get final valuejs
import {
$, get, set, cleanInlineStyles, remove, sync, keepTime,
random, createSeededRandom, randomPick, shuffle,
round, clamp, snap, wrap, mapRange, lerp, damp,
roundPad, padStart, padEnd, degToRad, radToDeg,
utils,
} from 'animejs';
// DOM相关
$('.selector') // querySelectorAll -> 数组
get(target, 'x') // 获取属性当前值
set(target, { x: 100 }) // 立即设置值
cleanInlineStyles(target) // 移除动画留下的内联样式
remove(target) // 从所有活跃动画中移除目标元素
sync(fn) // 在下一引擎帧运行fn
keepTime(timer) // 还原时保留计时器时间
// 数字相关
random(0, 100) // 0到100之间的随机数
random(0, 100, 2) // 指定小数位数
createSeededRandom(seed) // 可复现的随机生成器 -> fn()
randomPick([a, b, c]) // 从数组中随机选取元素
shuffle([1, 2, 3, 4]) // 原地打乱数组(会修改原数组)
round(3.1415, 2) // -> 3.14
clamp(value, min, max) // 将值限制在范围内
snap(value, increment) // 四舍五入到指定增量
snap(value, [0,50,100]) // 四舍五入到数组中的最近值
wrap(value, min, max) // 将值包裹在范围内(取模)
mapRange(value, inMin, inMax, outMin, outMax) // 将值在两个范围间映射
lerp(a, b, t) // 线性插值
damp(current, target, lambda, dt) // 平滑阻尼(帧率无关)
roundPad(value, decimals) // 四舍五入并补零:1.5 -> "1.50"
padStart(str, length, char) // 左侧补全
padEnd(str, length, char) // 右侧补全
degToRad(180) // -> Math.PI
radToDeg(Math.PI) // -> 180
// 链式工具函数
utils(value)
.round(2)
.clamp(0, 100)
.mapRange(0, 100, 0, 1)
.get() // 获取最终值14. WAAPI — Enhanced Web Animation API
14. WAAPI — 增强版Web动画API
Uses browser hardware acceleration for transforms and opacity.
js
import { waapi } from 'animejs';
// waapi.animate() — same API as animate() but uses WAAPI internally
waapi.animate('.box', {
x: 200,
opacity: 0,
duration: 1000,
ease: 'outExpo',
});
// Improvements over native WAAPI:
// - Sensible defaults
// - Multi-target support
// - Automatic units (no explicit 'px' needed)
// - Function-based values
// - Individual CSS transforms (x, y, rotate, scale...)
// - Per-property parameters
// - Spring and custom easings
// API differences vs native WAAPI:
// loop -> iterations
// alternate -> direction: 'alternate'
// ease -> easing
// .then() -> .finished
// Convert anime.js easing to WAAPI format
const easing = waapi.convertEase('outElastic(1, .5)');
// -> CustomEffect function for use in native WAAPI使用浏览器硬件加速处理变换和透明度。
js
import { waapi } from 'animejs';
// waapi.animate() — 与animate()API相同,但内部使用WAAPI
waapi.animate('.box', {
x: 200,
opacity: 0,
duration: 1000,
ease: 'outExpo',
});
// 相比原生WAAPI的改进:
// - 合理的默认值
// - 多目标支持
// - 自动单位(无需显式'px')
// - 基于函数的取值
// - 独立CSS变换(x、y、rotate、scale...)
// 按属性设置参数
// - 弹簧和自定义缓动
// 与原生WAAPI的API差异:
// loop -> iterations
// alternate -> direction: 'alternate'
// ease -> easing
// .then() -> .finished
// 将anime.js缓动转换为WAAPI格式
const easing = waapi.convertEase('outElastic(1, .5)');
// -> 用于原生WAAPI的CustomEffect函数When to use WAAPI vs JS engine
何时使用WAAPI vs JS引擎
| Use WAAPI when... | Use JS engine when... |
|---|---|
| Only transforms and opacity | Color animations |
| Maximum performance matters | JS objects / custom properties |
| You don't need JS callbacks | You need precise onUpdate |
| GPU-accelerated properties | Layout / scroll sync |
| 使用WAAPI的场景 | 使用JS引擎的场景 |
|---|---|
| 仅处理变换和透明度 | 颜色动画 |
| 追求极致性能 | JS对象/自定义属性 |
| 不需要JS回调 | 需要精确的onUpdate |
| GPU加速属性 | 布局/滚动同步 |
15. Engine — Global engine
15. Engine — 全局引擎
js
import { engine } from 'animejs';
// Parameters (configure the global engine)
engine.timeUnit = 'ms'; // 'ms' | 's' — time unit (ms by default)
engine.speed = 1; // global speed multiplier
engine.fps = 60; // global max FPS
engine.precision = 4; // decimal precision
engine.pauseOnDocumentHidden = true; // pause when the tab is hidden
// Methods
engine.update(); // manually advance the engine (manual mode)
engine.pause(); // pause all timers/animations
engine.resume(); // resume the engine
// Properties
engine.currentTime // current engine time
engine.paused // boolean
// Defaults — global default values
engine.defaults.duration = 400;
engine.defaults.ease = 'outQuad';
// ... any animation/playback parameterjs
import { engine } from 'animejs';
// 参数(配置全局引擎)
engine.timeUnit = 'ms'; // 'ms' | 's' — 时间单位(默认ms)
engine.speed = 1; // 全局速度乘数
engine.fps = 60; // 全局最大帧率
engine.precision = 4; // 小数精度
engine.pauseOnDocumentHidden = true; // 标签页隐藏时暂停
// 方法
engine.update(); // 手动推进引擎(手动模式)
engine.pause(); // 暂停所有计时器/动画
engine.resume(); // 恢复引擎
// 属性
engine.currentTime // 当前引擎时间
engine.paused // 布尔值
// 默认值 — 全局默认参数
engine.defaults.duration = 400;
engine.defaults.ease = 'outQuad';
// ... 任何动画/播放参数Common usage patterns
常见使用模式
Basic animation
基础动画
js
import { animate } from 'animejs';
animate('.box', {
x: 250,
duration: 800,
ease: 'inOutExpo',
loop: true,
alternate: true,
});js
import { animate } from 'animejs';
animate('.box', {
x: 250,
duration: 800,
ease: 'inOutExpo',
loop: true,
alternate: true,
});Timeline sequence
时间线序列
js
import { createTimeline, stagger } from 'animejs';
createTimeline({ loop: true })
.add('.logo', { opacity: [0,1], y: [-20,0], duration: 600 })
.add('.title', { opacity: [0,1], x: [-30,0], delay: stagger(50) })
.add('.cta', { scale: [0.8,1], opacity: [0,1] }, '-=200');js
import { createTimeline, stagger } from 'animejs';
createTimeline({ loop: true })
.add('.logo', { opacity: [0,1], y: [-20,0], duration: 600 })
.add('.title', { opacity: [0,1], x: [-30,0], delay: stagger(50) })
.add('.cta', { scale: [0.8,1], opacity: [0,1] }, '-=200');Scroll-synced animation
滚动同步动画
js
import { animate, onScroll } from 'animejs';
animate('.parallax', {
y: ['-20%', '20%'],
ease: 'linear',
autoplay: onScroll({ sync: true }),
});js
import { animate, onScroll } from 'animejs';
animate('.parallax', {
y: ['-20%', '20%'],
ease: 'linear',
autoplay: onScroll({ sync: true }),
});Text animation
文本动画
js
import { splitText, animate, stagger } from 'animejs';
const { chars } = splitText('.hero-title', { chars: true });
animate(chars, {
opacity: [0, 1],
y: [30, 0],
rotateX: [-90, 0],
delay: stagger(40, { from: 'center' }),
duration: 700,
ease: 'outBack',
});js
import { splitText, animate, stagger } from 'animejs';
const { chars } = splitText('.hero-title', { chars: true });
animate(chars, {
opacity: [0, 1],
y: [30, 0],
rotateX: [-90, 0],
delay: stagger(40, { from: 'center' }),
duration: 700,
ease: 'outBack',
});SVG line drawing on scroll
滚动触发SVG描边动画
js
import { animate, createDrawable, onScroll, stagger } from 'animejs';
animate(createDrawable('path'), {
draw: ['0 0', '0 1'],
delay: stagger(40),
ease: 'inOut(3)',
autoplay: onScroll({ sync: true }),
});js
import { animate, createDrawable, onScroll, stagger } from 'animejs';
animate(createDrawable('path'), {
draw: ['0 0', '0 1'],
delay: stagger(40),
ease: 'inOut(3)',
autoplay: onScroll({ sync: true }),
});Draggable with spring
带弹簧效果的拖拽
js
import { createDraggable, createSpring } from 'animejs';
createDraggable('.card', {
container: '.board',
snap: 100,
releaseEase: createSpring({ stiffness: 200, damping: 20 }),
});js
import { createDraggable, createSpring } from 'animejs';
createDraggable('.card', {
container: '.board',
snap: 100,
releaseEase: createSpring({ stiffness: 200, damping: 20 }),
});Responsive scope
响应式作用域
js
import { createScope, createTimeline, stagger } from 'animejs';
createScope({
mediaQueries: { mobile: '(max-width: 768px)' },
}).add(({ matches }) => {
createTimeline()
.add('.nav-item', {
x: matches.mobile ? ['-100%', 0] : [0, 0],
y: matches.mobile ? 0 : [-20, 0],
delay: stagger(60),
});
});js
import { createScope, createTimeline, stagger } from 'animejs';
createScope({
mediaQueries: { mobile: '(max-width: 768px)' },
}).add(({ matches }) => {
createTimeline()
.add('.nav-item', {
x: matches.mobile ? ['-100%', 0] : [0, 0],
y: matches.mobile ? 0 : [-20, 0],
delay: stagger(60),
});
});2D grid stagger
2D网格交错
js
import { animate, stagger } from 'animejs';
animate('.cell', {
scale: [0, 1],
delay: stagger(50, {
grid: [10, 10],
from: 'center',
}),
duration: 600,
ease: 'outBack',
});js
import { animate, stagger } from 'animejs';
animate('.cell', {
scale: [0, 1],
delay: stagger(50, {
grid: [10, 10],
from: 'center',
}),
duration: 600,
ease: 'outBack',
});Animatable for mouse tracking
鼠标追踪的可动画对象
js
import { createAnimatable } from 'animejs';
const blob = createAnimatable('.blob', {
x: { duration: 800, ease: 'outExpo' },
y: { duration: 800, ease: 'outExpo' },
});
document.addEventListener('mousemove', (e) => {
blob.x(e.clientX - 50);
blob.y(e.clientY - 50);
});js
import { createAnimatable } from 'animejs';
const blob = createAnimatable('.blob', {
x: { duration: 800, ease: 'outExpo' },
y: { duration: 800, ease: 'outExpo' },
});
document.addEventListener('mousemove', (e) => {
blob.x(e.clientX - 50);
blob.y(e.clientY - 50);
});Quick reference: tween composition
快速参考:补间合成
| Value | Behaviour |
|---|---|
| Replaces the current animation |
| Adds to the current value (accumulates) |
| Smoothly blends with the current animation |
js
// Blend composition for interactive transforms
animate('.el', {
x: mouseX,
composition: 'blend',
});| 值 | 行为 |
|---|---|
| 替换当前动画 |
| 叠加到当前值(累积) |
| 与当前动画平滑混合 |
js
// 交互式变换使用混合合成
animate('.el', {
x: mouseX,
composition: 'blend',
});See also
相关链接
- react-19 — React animations with Anime.js
- frontend-design — UI animations and micro-interactions
- javascript — Using Anime.js with vanilla JavaScript
- react-19 — 使用Anime.js实现React动画
- frontend-design — UI动画与微交互
- javascript — 在原生JavaScript中使用Anime.js
References
参考资源
| Resource | URL |
|---|---|
| Official documentation | https://animejs.com/documentation |
| Easings editor | https://animejs.com/easing-editor |
| CodePen examples | https://codepen.io/collection/Poerqa |
| GitHub | https://github.com/juliangarnier/anime |
| npm | https://www.npmjs.com/package/animejs |