Animejs 开源项目解读
项目信息
- 项目名称:Animejs
- 项目描述: Animejs 一个零依赖、模块化、高性能的 JavaScript 动画引擎,通过 Clock → Timer → Animation/Timeline 的分层继承架构,提供 CSS/SVG/DOM/JS Object 的统一动画 API。
- 项目地址:https://github.com/juliangarnier/anime
- 官方文档:https://animejs.com
解决的核心痛点:
- Web 动画 API 碎片化:CSS Transition/Animation、WAAPI、SVG 动画、Canvas/WebGL 各自有不同的接口和控制方式,Anime.js 提供统一 API 屏蔽底层差异
- 复杂动画编排困难:原生 API 缺乏时间线编排能力,Anime.js 内建 Timer → Animation → Timeline 的分层模型
- 高性能与代码量平衡:通过模块化 ESM 导出和零运行时依赖的设计,实现功能完备但按需加载的架构
核心架构速览
功能扩展层 (SVG / Text / WAAPI / Events / Easings / ...)
↓
动画抽象层 (Timer → JSAnimation / Timeline / Draggable)
↓
核心引擎层 (Clock / Engine / Render / Values)
↓
基础设施层 (Consts / Helpers / Globals)1. 项目概览
1.1 项目定位与核心价值
Anime.js 是一个快速、多功能、轻量级的 JavaScript 动画引擎库,提供简洁而强大的 API,支持 CSS 属性、SVG、DOM 属性和 JavaScript 对象动画。
解决的核心痛点:
- Web 动画 API 碎片化:CSS Transition/Animation、WAAPI、SVG 动画、Canvas/WebGL 各自有不同的接口和控制方式,Anime.js 提供统一 API 屏蔽底层差异
- 复杂动画编排困难:原生 API 缺乏时间线编排能力,Anime.js 内建 Timer → Animation → Timeline 的分层模型
- 高性能与代码量平衡:通过模块化 ESM 导出和零运行时依赖的设计,实现功能完备但按需加载的架构
1.2 目标用户与使用场景
- Web 前端开发者:需要在项目中快速添加复杂交互动画
- 创意设计师/开发者:需要制作高视觉效果的交互动画
- 框架无关:可在任何 Web 项目中使用 (Vanilla JS / React / Vue 等)
1.3 核心技术亮点
| 特性 | 说明 |
|---|---|
| 零运行时依赖 | 不依赖任何第三方库 |
| 模块化架构 | 14 个独立可导入子模块,Tree Shaking 友好 |
| 统一动画模型 | CSS/DOM/SVG/JS Object 统一 API |
| 高性能渲染 | rAF 主循环 + 链表遍历 + 帧节流 |
| 值系统 | 自动识别 NUMBER/UNIT/COLOR/COMPLEX 四种类型 |
| 合成系统 | replace/blend/none 三种 Tween 冲突处理 |
| Promise 支持 | .then() 方法支持 await 语法 |
| 丰富扩展 | SVG 描边/变形/路径、文本分割/乱序、拖拽、滚动驱动 |
1.4 技术栈与选型对比
| 层面 | 技术选型 | 权衡考量 |
|---|---|---|
| 语言 | JavaScript ESM | Tree Shaking 友好,无编译步骤 |
| 类型 | JSDoc + TS .d.ts | 保持 JS 开发体验同时提供完整类型 |
| 构建 | Rollup | ESM/CJS/UMD/IIFE 多格式输出 |
| 架构 | 分层继承 (Clock→Timer→Animation) | 复用时间管理逻辑,代价是降低灵活性 |
| 渲染 | 自建 rAF 循环 | 精确控制每帧,支持复杂编排 |
| WAAPI | 可选集成模块 | 保留高性能原生动画路径 |
2. 整体架构设计
2.1 架构概述
Anime.js V4 采用 分层继承架构,从底层到顶层分为四个层次:
- 基础设施层 (Infrastructure):环境检测、浏览器 API 适配、常量定义
- 核心引擎层 (Core Engine):Clock 时间系统、Render 渲染循环、Values 值处理系统、全局 Engine 单例
- 动画抽象层 (Animation Abstractions):Timer 基类 → Animation(单动画)/Timeline(时间线编排)/Draggable(拖拽)
- 功能扩展层 (Extensions):Easings 缓动、SVG 工具、Text 文本、WAAPI 桥接、Events 事件、Scope 作用域
2.2 整体架构图
+=======================================================================+
| 功能扩展层 (Extensions) |
| +----------+ +----------+ +----------+ +-----------+ |
| | SVG | | Text | | WAAPI | | Events | |
| | drawable | | split | | waapi() | | scroll | |
| | morphTo | | scramble | | animate | | observer | |
| | motion | | | | | | | |
| +----+-----+ +----+-----+ +----+-----+ +-----+-----+ |
| | | | | |
| +----+-----+ +----+-----+ +----+-----+ +-----+-----+ |
| | Layout | | Easings | | Scope | | Utils | |
| | animate | | eases | | scope() | | stagger | |
| | layout | | spring | | refresh | | random | |
| | | | cubic- | | revert | | chainable | |
| | | | bezier | | | | | |
| +----------+ +----------+ +----------+ +-----------+ |
+=======================================================================+
| (import)
v
+=======================================================================+
| 动画抽象层 (Animation Abstractions) |
| |
| +-----------------------------------------------------------------+ |
| | Timer (继承 Clock) | |
| | - 生命周期: began/completed/paused | |
| | - 时间控制: seek/reset/restart/reverse/alternate | |
| | - 子节点: _head/_tail 链表管理 | |
| | - 回调: onBegin/onUpdate/onLoop/onComplete | |
| | - Promise: .then() 支持 | |
| +-------+-------------------+-------------------+-----------+------+ |
| | | | | |
| v v v v |
| +---------------+ +----------------+ +----------------+ +-------+ |
| | JSAnimation | | Timeline | | Draggable | | Anim- | |
| | (Animation) | | (时间线编排) | | (拖拽交互) | | atable| |
| | - _tweens链表 | | - _children | | - snap/x/y | | (CSS) | |
| | - tween合成 | | 位置计算 | | - inertia | +-------+ |
| | - 值分解 | | - add()/set() | | - modifiers | | |
| +---------------+ +----------------+ +----------------+ | |
+=======================================================================+
| (继承/调用)
v
+=======================================================================+
| 核心引擎层 (Core Engine) |
| |
| +------------------+ +------------------+ +--------------------+ |
| | Clock | | Engine (单例) | | Render / tick() | |
| | - _currentTime | | - _lastTickTime | | - render() 核心 | |
| | - _fps/_speed | | - reqId (rAF) | | 渲染循环 | |
| | - requestTick() | | - _head (链表) | | - tick() 子节点 | |
| | - deltaTime | | - wake() | | 递归遍历 | |
| +------------------+ +------------------+ +--------------------+ |
| |
| +------------------+ +------------------+ +--------------------+ |
| | Values | | Styles | | Transforms | |
| | - decomposeValue | | - sanitizeProp | | - decomposeTransform| |
| | - composeColor | | - revertValues | | - buildString | |
| | - composeComplex | | | | | |
| +------------------+ +------------------+ +--------------------+ |
| |
| +------------------+ +------------------+ +--------------------+ |
| | Units | | Colors | | Targets | |
| | - convertUnit | | - parse/rgb/hsl | | - registerTargets | |
| +------------------+ +------------------+ +--------------------+ |
+=======================================================================+
| (依赖)
v
+=======================================================================+
| 基础设施层 (Infrastructure) |
| +------------------+ +------------------+ +--------------------+ |
| | Consts | | Helpers | | Globals | |
| | - isBrowser | | - now() | | - globals.timeScale| |
| | - tweenTypes | | - addChild() | | - defaults配置 | |
| | - valueTypes | | - forEachChild() | | - scope.current | |
| | - tickModes | | - lerp/clamp | | | |
| +------------------+ +------------------+ +--------------------+ |
+=======================================================================+分层职责说明:
| 层次 | 核心职责 | 关键技术 |
|---|---|---|
| 基础设施层 | 环境检测、常量枚举、工具函数、全局状态 | 浏览器/Node 双环境适配 |
| 核心引擎层 | 时间系统、帧调度、值解析、渲染循环 | rAF 主循环、链表遍历 |
| 动画抽象层 | Timer 基类、Animation、Timeline 编排、Draggable 交互 | 类继承、双向链表 |
| 功能扩展层 | SVG 动画、文本特效、WAAPI 桥接、缓动函数 | 可选的独立模块 |
2.3 目录结构
anime/
├── src/ # 【核心基建】源代码主目录 - 61个JS文件,~37K行
│ ├── index.js # 【核心基建】全局入口 - re-export 14个模块的所有公共API
│ │
│ ├── core/ # 【核心基建】核心引擎基础设施层 - 11个文件
│ │ ├── clock.js # 【核心基建】Clock 时间基类 - 所有定时实体的父类
│ │ ├── consts.js # 【核心基建】全局常量 - 环境检测、枚举(tweenTypes/valueTypes/tickModes/compositionTypes)、浏览器DOM符号
│ │ ├── colors.js # 【核心基建】颜色处理 - 颜色解析与格式化
│ │ ├── globals.js # 【核心基建】全局状态 - globalVersions版本数组、defaults默认参数、scope管理
│ │ ├── helpers.js # 【工具集】通用工具 - now()/clamp()/lerp()/addChild()/forEachChildren()/mergeObjects()等
│ │ ├── render.js # 【核心基建】渲染核心 - render()计算单帧Tween值写入目标、tick()递归处理子节点(Timeline)
│ │ ├── styles.js # 【核心基建】样式处理 - sanitizePropertyName()属性名标准化(如line-height→lineHeight)、revertValues()恢复
│ │ ├── targets.js # 【核心基建】目标管理 - registerTargets()、parseTargets()加载DOM元素/NodeList/对象
│ │ ├── transforms.js # 【核心基建】Transform处理 - CSS Transform分解为独立属性、buildTransformString()重建
│ │ ├── units.js # 【核心基建】单位处理 - convertValueUnit()单位转换(px↔rem↔vh等)
│ │ └── values.js # 【核心基建】值系统 - decomposeRawValue()分解值类型、composeColorValue()/composeComplexValue()合成、getRelativeValue()相对值
│ │
│ ├── timer/ # 【核心基建】Timer模块 - 动画引擎的核心时间抽象
│ │ ├── index.js # 【核心基建】导出 createTimer() 工厂函数
│ │ └── timer.js # 【核心基建】Timer类(继承Clock) - 生命周期管理、seek/pause/resume/reverse/stretch、Promise支持
│ │
│ ├── animation/ # 【业务模块】Animation模块 - 属性动画实现
│ │ ├── index.js # 【业务模块】导出 animate()、createAnimations()、stagger()
│ │ ├── animation.js # 【业务模块】JSAnimation类(继承Timer) - Tween链表创建、值解析与写入
│ │ ├── composition.js # 【核心基建】Tween合成系统 - composeTween()处理replace/blend/none、WeakMap存储target+property→Tween映射
│ │ └── additive.js # 【核心基建】加法动画 - 相对值叠加(additive)、animation.add()累加
│ │
│ ├── timeline/ # 【业务模块】Timeline模块 - 多动画时间编排
│ │ ├── index.js # 【业务模块】导出 createTimeline()
│ │ ├── timeline.js # 【业务模块】Timeline类(继承Timer) - add()/set()/sync()/remove()、子动画链表遍历渲染
│ │ └── position.js # 【工具集】位置解析 - parseTimelinePosition()处理绝对/相对/标签偏移
│ │
│ ├── easings/ # 【核心基建】缓动函数系统 - 8种缓动类型
│ │ ├── index.js # 【核心基建】导出 parseEase() 统一缓动解析入口
│ │ ├── none.js # 【核心基建】无缓动恒等函数
│ │ ├── eases/ # 【核心基建】标准Penner缓动集 - in/out/inOut × Quad/Cubic/Quart/Quint/Sine/Expo/Circ/Back/Elastic/Bounce
│ │ │ ├── index.js # 【核心基建】预定义缓动函数导出
│ │ │ └── parser.js # 【核心基建】缓动名称→函数解析器
│ │ ├── linear/ ── index.js # 【核心基建】linear()/none() 线性缓动
│ │ ├── steps/ ── index.js # 【核心基建】steps() 阶梯缓动
│ │ ├── irregular/ ── index.js # 【核心基建】irregular() 自定义关键帧缓动(如[0, 0.2, 0.8, 1])
│ │ ├── cubic-bezier/ ── index.js # 【核心基建】cubicBezier() CSS贝塞尔缓动
│ │ └── spring/ ── index.js # 【核心基建】spring() 物理弹簧缓动(mass/stiffness/damping)
│ │
│ ├── engine/ # 【核心基建】全局动画引擎
│ │ ├── index.js # 【核心基建】导出 engine 全局单例
│ │ └── engine.js # 【核心基建】Engine类(继承Clock) - rAF主循环、Timer链表管理、全局timeScale/pause控制
│ │
│ ├── animatable/ # 【业务模块】Animatable - CSS computed style动画
│ │ ├── index.js # 【业务模块】导出 animateComputedStyle()等
│ │ └── animatable.js # 【业务模块】Animatable类(继承Timer) - 驱动CSS过渡/WAAPI动画
│ │
│ ├── draggable/ # 【业务模块】Draggable - 拖拽交互
│ │ ├── index.js # 【业务模块】导出 createDraggable()
│ │ └── draggable.js # 【业务模块】Draggable类(继承Timer) - 鼠标/触摸拖拽、snap吸附、inertia惯性、modifiers修饰
│ │
│ ├── scope/ # 【核心基建】Scope - 动画生命周期管理
│ │ ├── index.js # 【核心基建】导出 createScope()
│ │ └── scope.js # 【核心基建】Scope类 - register()/refresh()/revert()/pause()批量控制
│ │
│ ├── events/ # 【业务模块】Events - 滚动驱动
│ │ ├── index.js # 【业务模块】导出 createScrollObserver()
│ │ └── scroll.js # 【业务模块】ScrollObserver - 滚动位置→动画时间的映射、link()/unlink()
│ │
│ ├── layout/ # 【业务模块】Layout - 布局动画
│ │ ├── index.js # 【业务模块】导出 animateLayout()
│ │ └── layout.js # 【业务模块】FLIP布局动画实现 - First/Last/Invert/Play
│ │
│ ├── svg/ # 【业务模块】SVG - 矢量图形动画专属
│ │ ├── index.js # 【业务模块】导出 createDrawable()、createMorphTo()、createMotionPath()
│ │ ├── drawable.js # 【业务模块】Drawable - SVG描边动画(stroke-dashoffset/stroke-dasharray)
│ │ ├── helpers.js # 【工具集】SVG工具 - 路径解析、长度计算
│ │ ├── morphto.js # 【业务模块】MorphTo - SVG path d属性形状变换
│ │ └── motionpath.js # 【业务模块】MotionPath - SVG路径跟随运动
│ │
│ ├── text/ # 【业务模块】Text - 文本动画特效
│ │ ├── index.js # 【业务模块】导出 splitText()、scrambleText()
│ │ ├── split.js # 【业务模块】SplitText - 文本按字符/单词/行分割为独立DOM元素
│ │ └── scramble.js # 【业务模块】ScrambleText - 字符乱序切换动画
│ │
│ ├── waapi/ # 【业务模块】WAAPI - Web Animations API桥接
│ │ ├── index.js # 【业务模块】导出 waapi.animate()
│ │ ├── waapi.js # 【业务模块】WAAPIAnimation(继承Timer) - 封装element.animate()
│ │ └── composition.js # 【业务模块】WAAPI Tween合成管理
│ │
│ ├── utils/ # 【工具集】通用工具集 - 7个独立工具
│ │ ├── index.js # 【工具集】导出所有工具函数
│ │ ├── chainable.js # 【工具集】链式调用辅助 - 支持 obj.x(100).y(200).duration(1000) 语法
│ │ ├── number.js # 【工具集】数值工具 - 数值格式化、精度处理
│ │ ├── random.js # 【工具集】随机工具 - random()/randomInt() 随机值生成
│ │ ├── stagger.js # 【工具集】交错延迟 - stagger()按元素索引计算延迟
│ │ ├── target.js # 【工具集】目标查找 - querySelectorAll()封装、NodeList→Array
│ │ └── time.js # 【工具集】时间工具 - 时间格式化转换
│ │
│ └── types/ # 【配置】JSDoc类型定义文件
│ └── index.js # 【配置】全局@typedef类型 - TimerParams/AnimationParams/Tween/Target等,构建时提取注入bundle头部
│
├── dist/ # 【配置】构建产物
│ ├── modules/ # 【配置】ESM + CJS 模块输出 (preserveModules)
│ └── bundles/ # 【配置】UMD + ESM 打包输出 (anime.*.js)
│
├── examples/ # 【配置】78个示例页面 (官方示例)
├── tests/ # 【质量保证】测试套件 (120个文件,Mocha + Chai)
│ ├── index.html # 【质量保证】浏览器测试入口
│ └── suites/ # 【质量保证】测试用例目录 (浏览器 + Node.js)
│
├── assets/ # 【配置】仓库静态资源 (Logo、GIF、赞助商图片)
├── .github/ # 【配置】GitHub CI/CD配置
├── package.json # 【配置】NPM包配置 - v4.4.1, 18个子路径导出, 零运行时依赖
├── rollup.config.js # 【配置】Rollup构建配置 - ESM/CJS/UMD多格式输出
├── tsconfig.json # 【配置】TypeScript主配置
├── tsconfig.types.json # 【配置】类型声明生成配置 - 输出dist/modules/**/*.d.ts
├── CONTRIBUTING.md # 【配置】贡献指南
├── LICENSE.md # 【配置】MIT开源协议
└── README.md # 【配置】英文项目主文档3. 模块依赖与调用关系
3.1 全局入口与核心路由
逻辑说明:src/index.js 作为全局入口,将所有 14 个模块的子入口聚合导出。每个模块有自己的 index.js,对外暴露特定的公共 API 函数。模块内部通过 core/ 共享基础设施。Engine 是全局单例,负责驱动所有活跃的 Timer 实例。
- 调用拓扑 (plainText):
src/index.js (全局入口 - 14个模块聚合)
|
+---> src/timer/index.js --------> createTimer() ────> new Timer(Clock)
|
+---> src/animation/index.js -----> animate() ────────> new JSAnimation(Timer)
| stagger()
| createAnimations()
|
+---> src/timeline/index.js ------> createTimeline() ─> new Timeline(Timer)
| |
| +--> add() -> new JSAnimation
| +--> set() -> new JSAnimation
|
+---> src/draggable/index.js -----> createDraggable() ─> new Draggable(Timer)
|
+---> src/scope/index.js ---------> createScope() ─────> new Scope()
| scope.refresh()
| scope.revert()
|
+---> src/engine/index.js --------> engine (全局单例)
| engine.resume()
| engine.pause()
|
+---> src/events/index.js --------> createScrollObserver()
|
+---> src/easings/index.js -------> parseEase()
| ├── src/easings/eases/ ------> 预定义缓动函数集
| ├── src/easings/cubic-bezier/ -> cubicBezier()
| ├── src/easings/spring/ ------> spring()
| ├── src/easings/steps/ -------> steps()
| ├── src/easings/linear/ ------> linear()
| └── src/easings/irregular/ ---> irregular()
|
+---> src/svg/index.js -----------> createDrawable()
| createMorphTo()
| createMotionPath()
|
+---> src/text/index.js -----------> splitText()
| scrambleText()
|
+---> src/layout/index.js ---------> animateLayout()
|
+---> src/waapi/index.js ----------> waapi.animate()
|
+---> src/animatable/index.js -----> animateComputedStyle()
|
+---> src/utils/index.js ----------> stagger()
| random()
| chainable()
|
+---> src/types/index.js ----------> (JSDoc 类型定义,仅用于类型检查)3.2 核心业务实体与关联
实体定义:
| 实体 | 说明 | 在系统中的角色 |
|---|---|---|
| Clock | 时间基类,管理帧率和播放速率 | 所有可定时实体的基础 |
| Timer | 动画时间控制器,继承 Clock | Animation/Timeline/Draggable 的基类 |
| Engine | 全局动画引擎单例,继承 Clock | 驱动主循环,管理所有活跃 Timer |
| JSAnimation | 单次动画,继承 Timer | 操作 Tween 链表,驱动属性动画 |
| Tween | 动画单元,表示单个属性的插值 | 包含起止值、缓动、类型信息 |
| Timeline | 动画时间线,继承 Timer | 管理多个子 Animation 的时间编排 |
| Draggable | 拖拽控制器,继承 Timer | 封装鼠标/触摸交互到动画 |
| Scope | 作用域管理器 | 批量控制一组动画的生命周期 |
| ScrollObserver | 滚动观察器 | 将滚动位置映射为动画时间 |
| Animatable | CSS 过渡动画控制器 | 驱动 computed style 过渡 |
实体引用拓扑 (plainText):
[Clock]
|
+------ 1 -----> 1 [Engine] (全局单例)
|
+------ 1 -----> N [Timer]
|
+------ 1 -----> N [JSAnimation]
| |
| +-- 1 -----> N [Tween] (属性插值单元)
| |
| +-- 1 -----> 1 [Composition] (合成模式)
|
+------ 1 -----> N [Timeline]
| |
| +-- 1 -----> N [JSAnimation] (子动画)
|
+------ 1 -----> N [Draggable]
|
+------ 1 -----> N [Animatable]
[Engine] 1 -----> N [Timer] (双向链表: _head/_tail)
[Scope] 1 -----> N [Timer] (作用域内注册的动画/时间线)
[ScrollObserver] 1 -----> 1 [Timer] (linked 关联)
[Tween]
+-- 1 -----> 1 [Target] (DOM元素或JS对象)
+-- 1 -----> 1 [Ease] (缓动函数)
+-- 1 -----> 0..1 [Modifier] (值修饰函数)4. 核心模块详解
模块一:Clock - 时间基类
模块名称:Clock(时间系统)
设计说明:Clock 是所有时间相关实体的最底层基类。它封装了帧率控制(
_fps)、播放速率(_speed)、时间计算(requestTick、computeDeltaTime)和子节点链表管理(_head/_tail)。Clock 不负责渲染,只负责时间调度。通过requestTick(time)方法判断当前帧是否需要更新(基于帧率的节流),返回tickModes.AUTO或tickModes.NONE。内部结构图 (plainText):
+--------------------------------------------------------+
| Clock (时间基类) |
| |
| 属性: |
| +------------------------------------+ |
| | _currentTime: Number | 当前绝对时间 |
| | _startTime: Number | 起始时间 |
| | _lastTickTime: Number | 上次 tick 时间 |
| | _scheduledTime: Number | 下次帧预定时间 |
| | _frameDuration: Number | 帧持续时间(ms) |
| | _fps: Number | 帧率 |
| | _speed: Number | 播放速率 |
| | _head: Tickable|null | 子节点链表头 |
| | _tail: Tickable|null | 子节点链表尾 |
| +------------------------------------+ |
| |
| 方法: |
| +------------------------------------+ |
| | requestTick(time) -> tickModes | 帧节流判断 |
| | computeDeltaTime(time) -> Number | 计算帧间隔 |
| +------------------------------------+ |
+--------------------------------------------------------+模块二:Timer - 动画时间基类
模块名称:Timer(动画时间基类)
设计说明:Timer 继承 Clock,是 Animation、Timeline、Draggable 的直接基类。它添加了完整的动画生命周期管理:began(开始)、completed(完成)、paused(暂停)。支持 delay、duration、loop(循环)、alternate(交替反向)、reversed(反向播放)。通过
seek()、reset()、restart()、stretch()等方法实现对时间的精确控制。内建 Promise 支持(.then()方法),允许开发者await动画完成。Timer 还实现了:revert()回到初始状态并取消、cancel()取消并从引擎移除、complete()立即完成。Timer 在构造函数中通过scope.current?.register(this)自动注册到当前作用域。内部结构图 (plainText):
+==================================================================+
| Timer (继承 Clock) |
| |
| +-----------------------------+ +-----------------------------+|
| | 生命周期状态 | | 循环控制 ||
| | - began: Boolean | | - iterationCount: Number ||
| | - completed: Boolean | | - iterationDuration: Number||
| | - paused: Boolean | | - _alternate: Boolean ||
| | - cancelled: Boolean | | - _reversed: Number ||
| +-----------------------------+ +-----------------------------+|
| |
| +-----------------------------+ +-----------------------------+|
| | 回调函数 | | 时间控制 ||
| | - onBegin | | - _offset: Number ||
| | - onBeforeUpdate | | - _delay: Number ||
| | - onUpdate | | - _loopDelay: Number ||
| | - onLoop | | - _priority: Number ||
| | - onPause | | ||
| | - onComplete | +-----------------------------+|
| +-----------------------------+ |
| |
| +--------------------------------------------------------------+ |
| | 核心方法 | |
| | init() -> this : 初始化动画参数、fps、speed | |
| | reset() -> this : 重置到初始状态 | |
| | restart() -> this : reset + resume | |
| | seek(time) -> this : 跳转到指定时间 | |
| | pause() -> this : 暂停动画 | |
| | resume() -> this : 恢复播放(添加到Engine链表) | |
| | play() -> this : 正向播放 | |
| | reverse() -> this : 反向播放 | |
| | alternate() -> this : 切换播放方向 | |
| | stretch(newDur) -> this: 拉伸时间 | |
| | cancel() -> this : 取消动画(从Engine移除) | |
| | revert() -> this : 回退 + 取消 | |
| | complete() -> this : 立即完成 | |
| | then(cb) -> Promise : Promise 化支持 await | |
| +--------------------------------------------------------------+ |
+==================================================================+模块三:Engine - 全局动画引擎
模块名称:Engine(全局动画引擎单例)
设计说明:Engine 是全局唯一的动画引擎实例,继承自 Clock。它使用
requestAnimationFrame(浏览器)或setImmediate(Node.js)驱动主循环。所有活跃的 Timer 通过双向链表(_head↔_next/_prev)注册到 Engine 上。每帧 Engine 遍历链表,按优先级排序后调用tick()进行渲染。Engine 管理:全局defaults配置(影响所有动画)、timeScale全局时间缩放、pauseOnDocumentHidden(页面隐藏时暂停)、_speed全局播放速率。内部结构图 (plainText):
+==================================================================+
| Engine (全局单例, 继承 Clock) |
| |
| +-------------------------------+ +----------------------------+|
| | 全局配置 | | 主循环驱动 ||
| | - defaults: DefaultsParams | | - reqId: Number ||
| | - useDefaultMainLoop: Bool | | - _lastTickTime: Number ||
| | - pauseOnDocumentHidden:Bool | | - _startTime: Number ||
| +-------------------------------+ | - engineTickMethod: rAF ||
| | - engineCancelMethod:cAF ||
| +-------------------------------+ +----------------------------+|
| | 链表管理 | |
| | - _head: Timer (最高优先级) | +----------------------------+|
| | - _tail: Timer (最低优先级) | | 核心方法 ||
| | - _hasChildren: Boolean | | - requestTick(time) ||
| +-------------------------------+ | - wake() : 唤醒引擎 ||
| | - pause() : 全局暂停 ||
| +-------------------------------+ | - resume() : 全局恢复 ||
| | 全局时间控制 | +----------------------------+|
| | - _speed: Number | |
| | - timeScale (globals) | |
| +-------------------------------+ |
+==================================================================+模块四:Render 渲染核心
模块名称:Render(渲染/心跳系统)
设计说明:
render()和tick()是 Anime.js 最核心的两个函数。render()负责计算单个 Tickable 的当前状态(时间、迭代、方向),然后遍历其 Tweens 链表,为每个 Tween 计算当前值并写入目标(DOM style/attribute 或 JS object)。tick()在render()基础上增加了对子节点的递归处理(针对 Timeline),实现子动画的顺序或反向渲染。两个函数密切配合:Engine 的每帧调用tick(engine, time),逐级传播到所有活跃的 Timer。内部结构图 (plainText):
+==================================================================+
| Render (核心渲染系统) |
| |
| tick(tickable, time, muteCallbacks, internalRender, tickMode) |
| | |
| +-----> 1. render(tickable, time, ...) 渲染自身 |
| | | |
| | +-- 计算: _currentTime, _iterationTime, backwards |
| | +-- 触发: onBegin, onLoop, onBeforeUpdate |
| | +-- 遍历 Tween 链表: |
| | | +-- 计算 tweenProgress (ease) |
| | | +-- lerp fromNumber -> toNumber |
| | | +-- composeValue: NUMBER|UNIT|COLOR|COMPLEX |
| | | +-- 写入目标: style/attribute/object |
| | +-- 触发: onUpdate, onRender |
| | +-- 处理: onComplete (循环/正常结束) |
| | |
| +-----> 2. 如果有子节点 (Timeline) |
| | |
| +-- 处理循环回调 (onLoop) |
| +-- 遍历子节点 (正向或反向) |
| | +-- render(child, childTime, ...) |
| +-- 触发 onRender |
| +-- 处理 onComplete (所有子节点完成) |
+==================================================================+模块五:Values 值处理系统
模块名称:Values(值解析与合成)
设计说明:Values 系统是 Anime.js 能处理多种值类型的关键。它将动画属性值分解为四种基本类型:NUMBER(纯数字)、UNIT(带单位的数字,如
100px)、COLOR(颜色,如#ff0000、rgb()、hsl())、COMPLEX(复合值,如10px 20px)。对于每种类型,系统能从原始值中提取fromNumber和toNumber,在渲染时通过lerp插值后重新合成为目标格式。此外,系统还支持函数值(每帧动态计算)、相对值(+=100形式)、以及 additive(加法动画叠加)。内部结构图 (plainText):
+==================================================================+
| Values (值处理核心) |
| |
| 输入: 原始值字符串/数字 ("100px", "#ff0", "10px 20px", 42) |
| | |
| v |
| decomposeRawValue(value) |
| +-- 识别类型: NUMBER | UNIT | COLOR | COMPLEX |
| +-- 提取结构: { numbers, strings, unit, type } |
| | |
| v |
| decomposeTweenValue(tween) |
| +-- 解析 from 值 (原始值/函数值/相对值) |
| +-- 解析 to 值 |
| +-- 处理 modifier (值修饰函数) |
| +-- 处理 composition (blend/replace/none) |
| +-- 存储: _fromNumber, _toNumber, _unit, _valueType |
| | |
| v (每帧渲染时) |
| | |
| lerp(fromNumber, toNumber, progress) -> 插值结果 |
| | |
| v |
| 合成输出: |
| +-- NUMBER: 直接返回值 |
| +-- UNIT: number + unit → "100px" |
| +-- COLOR: composeColorValue() → "rgb(128,255,0)" |
| +-- COMPLEX: composeComplexValue() → "10px 20px" |
+==================================================================+5. 关键数据流程
场景一:动画从创建到完成的生命周期
场景说明:用户调用
animate()创建一个动画。动画参数被解析为 Tweens 链表,通过 Engine 注册到主循环。每帧 Engine 唤醒后遍历活跃的 Timer,调用tick()→render()计算当前帧的 Tween 值并写入目标。当动画到达 duration 时触发 onComplete,从 Engine 链表中移除。这是 Anime.js 最核心的数据流,贯穿所有动画类型。流转时序图 (Mermaid):
场景二:Timeline 时间线编排
场景说明:用户创建 Timeline,通过
add()方法添加子动画。每个子动画在 Timeline 上的位置通过位置参数(绝对/相对/标签偏移)计算。Timeline 的_iterationTime驱动所有子动画的render(),子动画按_offset对齐到时间线的不同位置。这是实现复杂动画编排的核心机制。流转时序图 (Mermaid):
场景三:Tween 合成与冲突处理
场景说明:当多个动画同时修改同一目标的同一属性时,需要进行 Tween 合成(composition)。Anime.js 支持三种合成模式:
replace(覆盖旧动画)、blend(混合值)、none(独立运行)。合成系统通过WeakMap存储target + property → Tween[]的映射,在新动画创建时查找冲突并决定行为。流转时序图 (Mermaid):
6. 接口与契约规范
6.1 核心内部模块契约 (TypeScript)
// ============================================================
// Clock - 时间基类契约
// ============================================================
interface IClock {
/** 帧间隔时间 (只读) */
readonly deltaTime: number;
/** 当前绝对时间 */
_currentTime: number;
/** 起始时间 */
_startTime: number;
/** 上次 tick 时间 */
_lastTickTime: number;
/** 预定下次帧时间 */
_scheduledTime: number;
/** 帧持续时间 (K/fps) */
_frameDuration: number;
/** 帧率 */
_fps: number;
/** 播放速率 */
_speed: number;
/** 是否有子节点 */
_hasChildren: boolean;
/** 子节点链表头 */
_head: Tickable | Tween | null;
/** 子节点链表尾 */
_tail: Tickable | Tween | null;
/** 帧节流: 判断是否应该渲染当前帧 */
requestTick(time: number): TickMode;
/** 计算帧间隔 */
computeDeltaTime(time: number): number;
}
// ============================================================
// Timer - 动画时间基类契约
// ============================================================
interface ITimer extends IClock {
/** 唯一标识 */
id: string | number;
/** 父级 Timer (Timeline) */
parent: Timeline | null;
/** 总持续时间 */
duration: number;
/** 是否反向 */
backwards: boolean;
/** 暂停状态 */
paused: boolean;
/** 已开始标志 */
began: boolean;
/** 已完成标志 */
completed: boolean;
/** 单次迭代持续时间 */
iterationDuration: number;
/** 总迭代次数 */
iterationCount: number;
/** 当前迭代索引 */
_currentIteration: number;
/** 当前迭代内时间 */
_iterationTime: number;
/** 延迟偏移 */
_offset: number;
/** 取消标志 */
_cancelled: number;
/** 自动播放/滚动联动 */
_autoplay: boolean | ScrollObserver;
/** 进度 0-1 (get/set) */
progress: number;
/** 迭代进度 0-1 (get/set) */
iterationProgress: number;
/** 当前时间 (get/set) */
currentTime: number;
/** 迭代内当前时间 (get/set) */
iterationCurrentTime: number;
/** 当前迭代索引 (get/set) */
currentIteration: number;
/** 反向标志 (get/set) */
reversed: boolean;
/** 播放速度 (get/set) */
speed: number;
// 回调
onBegin: Callback<this>;
onBeforeUpdate: Callback<this>;
onUpdate: Callback<this>;
onLoop: Callback<this>;
onPause: Callback<this>;
onComplete: Callback<this>;
// 控制方法
init(internalRender?: boolean): this;
reset(softReset?: boolean): this;
restart(): this;
seek(time: number, muteCallbacks?: boolean, internalRender?: boolean): this;
pause(): this;
resume(): this;
play(): this;
reverse(): this;
alternate(): this;
stretch(newDuration: number): this;
cancel(): this;
revert(): this;
complete(muteCallbacks?: boolean): this;
then(callback?: Callback<ResolvedTimer>): Promise<this>;
resetTime(): this;
}
// ============================================================
// Tween - 动画属性插值单元契约
// ============================================================
interface ITween {
/** 目标对象 */
target: Target;
/** 属性名 */
property: string;
/** Tween 类型 */
_tweenType: TweenType; // OBJECT | ATTRIBUTE | CSS | TRANSFORM | CSS_VAR
/** 值类型 */
_valueType: ValueType; // NUMBER | UNIT | COLOR | COMPLEX
/** 起始数值 */
_fromNumber: number;
/** 结束数值 */
_toNumber: number;
/** CSS 单位 */
_unit: string;
/** 起始时间偏移 */
_startTime: number;
/** 变化持续时间 */
_changeDuration: number;
/** 更新持续时间 (含延迟) */
_updateDuration: number;
/** 合成模式 */
_composition: CompositionType; // replace | none | blend
/** 缓动函数 */
_ease: EaseFunction;
/** 值修饰函数 */
_modifier: ModifierFunction;
/** 当前时间 */
_currentTime: number;
/** 是否被覆盖 */
_isOverridden: boolean;
/** 是否被重叠 */
_isOverlapped: boolean;
/** 绝对起始时间 */
_absoluteStartTime: number;
/** 链表下一个 */
_next: Tween | null;
/** 链表上一个 */
_prev: Tween | null;
}
// ============================================================
// JSAnimation - 单次动画契约
// ============================================================
interface IJSAnimation extends ITimer {
/** Tween 链表头 */
_head: Tween | null;
/** Tween 链表尾 */
_tail: Tween | null;
/** 目标数组 */
targets: TargetsArray;
/** 默认参数 */
defaults: AnimationParams;
/** 渲染回调 */
onRender: Callback<this>;
/** 刷新动画值 (重新读取当前值) */
refresh(): this;
}
// ============================================================
// Timeline - 时间线编排契约
// ============================================================
interface ITimeline extends ITimer {
/** 默认子动画参数 */
defaults: AnimationParams;
/** 添加动画到时间线 */
add(
targets: TargetsParam,
params: AnimationParams,
position?: TimelinePosition
): this;
/** 设置属性 (立即生效) */
set(
targets: TargetsParam,
params: AnimationParams,
position?: TimelinePosition
): this;
/** 同步子动画 */
sync(): this;
/** 刷新所有子动画 */
refresh(): this;
/** 移除子动画 */
remove(targets: TargetsParam): this;
}
// ============================================================
// Engine - 全局引擎契约
// ============================================================
interface IEngine extends IClock {
/** 默认参数 */
defaults: DefaultsParams;
/** 是否使用默认主循环 */
useDefaultMainLoop: boolean;
/** 页面隐藏时暂停 */
pauseOnDocumentHidden: boolean;
/** 暂停状态 */
paused: boolean;
/** rAF/setImmediate ID */
reqId: number;
/** 上次 tick 时间 */
_lastTickTime: number;
/** 唤醒引擎 */
wake(): void;
/** 暂停引擎 */
pause(): this;
/** 恢复引擎 */
resume(): this;
}
// ============================================================
// 类型枚举
// ============================================================
declare const enum TweenType {
OBJECT = 0,
ATTRIBUTE = 1,
CSS = 2,
TRANSFORM = 3,
CSS_VAR = 4,
}
declare const enum ValueType {
NUMBER = 0,
UNIT = 1,
COLOR = 2,
COMPLEX = 3,
}
declare const enum TickMode {
NONE = 0,
AUTO = 1,
FORCE = 2,
}
declare const enum CompositionType {
replace = 0,
none = 1,
blend = 2,
}6.2 对外公共 API 契约 (函数签名)
// ============================================================
// 核心动画 API
// ============================================================
/**
* 创建单次动画
* @param targets - CSS选择器/DOM元素/NodeList/JS对象/数组
* @param parameters - 动画参数配置
* @returns JSAnimation 实例
*/
export function animate(
targets: TargetsParam,
parameters: AnimationParams
): JSAnimation;
/**
* 创建批量动画 (为每个目标创建独立动画)
* @param targets - 目标数组
* @param parameters - 动画参数
* @returns JSAnimation[]
*/
export function createAnimations(
targets: TargetsParam,
parameters: AnimationParams
): JSAnimation[];
// ============================================================
// 时间线 API
// ============================================================
/**
* 创建动画时间线
* @param parameters - Timeline 参数 (可选)
* @returns Timeline 实例
*/
export function createTimeline(
parameters?: TimelineParams
): Timeline;
// ============================================================
// 缓动函数 API
// ============================================================
/**
* 解析缓动函数 (字符串 → 函数)
* @param ease - 缓动名称字符串或函数
* @returns 缓动函数 (t: number) => number
*/
export function parseEase(
ease: string | EaseFunction
): EaseFunction;
/**
* 创建三次贝塞尔缓动
* @param x1, y1, x2, y2 - 贝塞尔控制点
* @returns 缓动函数
*/
export function cubicBezier(
x1: number, y1: number,
x2: number, y2: number
): EaseFunction;
/**
* 创建弹簧缓动
* @param parameters - 弹簧参数 (mass, stiffness, damping, velocity)
* @returns 缓动函数
*/
export function spring(
parameters?: SpringParams
): EaseFunction;
// ============================================================
// 工具 API
// ============================================================
/**
* 创建交错延迟
* @param value - 每个元素的延迟时间
* @param options - 交错选项 (from: 'start'|'center'|'end'|number)
* @returns StaggerFunction
*/
export function stagger(
value: number | StaggerFunction,
options?: { from?: 'start' | 'center' | 'end' | number }
): StaggerFunction;
// ============================================================
// 作用域 API
// ============================================================
/**
* 创建作用域
* @param parameters - 作用域配置
* @returns Scope 实例
*/
export function createScope(
parameters?: ScopeParams
): Scope;7. 构建与包结构
rollup.config.js
|
+-- 开发构建 (默认):
| 输入: src/**/index.js (从 package.json exports 自动提取)
| 输出: dist/modules/ (ESM + CJS, preserveModules)
|
+-- 生产构建 (build=true):
输入: src/index.js
输出: dist/bundles/anime.esm.js (ESM)
dist/bundles/anime.umd.js (UMD)
dist/bundles/anime.esm.min.js (ESM minified)
dist/bundles/anime.umd.min.js (UMD minified)
+ TypeScript: tsconfig.types.json → dist/modules/**/*.d.ts8. 快速开始
8.1 安装
npm install animejs8.2 基本用法
import { animate, stagger } from 'animejs';
animate('.square', {
x: 320,
rotate: { from: -180 },
duration: 1250,
delay: stagger(65, { from: 'center' }),
ease: 'inOutQuint',
loop: true,
alternate: true
});8.3 开发环境
npm i # 安装依赖
npm run dev # 开发模式 (监听 src/ 变化)
npm run build # 构建所有格式
npm run test:browser # 浏览器测试
npm run test:node # Node.js 测试
npm run open:examples # 浏览示例8.4 模块化导入
// 按需导入 (Tree Shaking 友好)
import { animate } from 'animejs';
import { createTimeline } from 'animejs/timeline';
import { spring } from 'animejs/easings/spring';
import { createDraggable } from 'animejs/draggable';
import { splitText } from 'animejs/text';