其他
在 Web/React 中用 Anime.js…
适用于使用 Anime.js 制作 Web/React 动画,并需要优化性能、组织复杂序列、处理 SVG/React 集成与清理的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 40/100 ×0.15
适用场景
在 Web/React 中用 Anime特定
解决思路
- 安装 Anime.js:`npm install animejs`。
- 按需导入:全量 `import anime from "animejs";`,或模块化 `import { animate, timeline, stagger } from "animejs";` 以减小包体积。
- 基础动画:调用 `anime({ targets: ".element", translateX: 250, rotate: "1turn", duration: 800, easing: "easeInOutQuad" });`。
- 控制帧率:设置 `anime.suspendWhenDocumentHidden = true;` 在页面隐藏时暂停。
- 控制特定动画 FPS:在 `anime({...})` 的 `update: function(anim) { ... }` 中按需做自定义帧率限制。
- 优先使用 GPU 加速 transform:动画属性用 `translateX`、`translateY`、`scale`、`rotate`、`opacity`。
- 避免触发布局重算:不要用 `left`、`top`、`width`、`height` 做动画。
- 高频更新用 Animatable:`import { Animatable } from "animejs";`,`const animatable = new Animatable(".cursor", { x: 0, y: 0 });`,在 `mousemove` 中更新 `animatable.x = e.clientX; animatable.y = e.clientY;`。
- 基础时间线:`const tl = anime.timeline({ easing: "easeOutExpo", duration: 750 });`。
- 向时间线添加序列:`tl.add({ targets: ".header", translateY: [-50, 0], opacity: [0, 1] })`,再 `.add({ targets: ".content", ... }, "-=500")` 等,通过 `"-=500"` 让动画重叠 500ms。
- 时间线控制:设置 `autoplay: false` 后使用 `tl.play(); tl.pause(); tl.restart(); tl.reverse(); tl.seek(1000);`。
- 基础交错动画:用 `delay: anime.stagger(100)` 让多个元素之间间隔 100ms。
- 交错从中心开始:`delay: anime.stagger(100, { from: "center" })`。
- 网格交错:`delay: anime.stagger(50, { grid: [14, 5], from: "center" })`。
- 带缓动的交错:`delay: anime.stagger(100, { easing: "easeOutQuad" })`。
- 使用内置缓动:如 `easing: "easeOutExpo"`、`"easeInOutQuad"`、`"easeOutElastic(1, .5)"`、`"easeOutBounce"`、`"spring(1, 80, 10, 0)"`。
- 自定义缓动:`easing: "cubicBezier(0.25, 0.1, 0.25, 1)"`。
- SVG 路径动画:`const path = anime.path(".motion-path");`,再动画 `translateX: path("x")`、`translateY: path("y")`、`rotate: path("angle")`,配合 `easing: "linear"`、`duration: 2000`、`loop: true`。
- SVG 线条绘制:`targets: "path"`,`strokeDashoffset: [anime.setDashoffset, 0]`,配合 `easing: "easeInOutSine"`、`duration: 1500`、`delay: anime.stagger(250)`。
- SVG 变形:`targets: "path"`,`d: [{ value: "M10 10 L90 10 L90 90 L10 90 Z" }, { value: "M10 50 Q50 10 90 50 Q50 90 10 50 Z" }]`,配合 `easing: "easeInOutQuad"`、`duration: 1000`、`loop: true`、`direction: "alternate"`。
- 函数式动态值:`translateX: function(el, i) { return i * 100; }`。
- 函数式旋转分配:`rotate: function(el, i, total) { return (360 / total) * i; }`。
- 函数式延迟:`delay: function(el, i) { return i * 50; }`。
- 动画事件:使用 `begin: function(anim) { ... }`、`update: function(anim) { ... }`(可读取 `anim.progress`)、`complete: function(anim) { ... }`。
- 循环与交替:设置 `direction: "alternate"`、`loop: true`,并用 `loopComplete: function(anim) { ... }` 监听每轮完成。
- React 基础用法:用 `useRef` 指向元素,在 `useEffect` 中 `anime({ targets: elementRef.current, ... })`,并在清理函数中 `animation.pause();`。
- React 受控动画:用 `elementRef`、`animationRef`,在 `useCallback` 中创建并保存 `anime({ targets: elementRef.current, translateX: [0, 250], duration: 800 })`,清理时 `animationRef.current?.pause();`,用按钮触发播放。
- 使用 WAAPI 桥接:`import { wapiAnimate } from "animejs";`,调用 `wapiAnimate(".element", { translateX: 250, duration: 800 });` 以获得浏览器原生性能。
- 尊重减少动态效果:用 `window.matchMedia("(prefers-reduced-motion: reduce)").matches`,将 `duration` 设为 `0` 或 `800`,`easing` 设为 `"linear"` 或 `"easeOutExpo"`。
- 最佳实践 1:优先使用 `translate`、`scale`、`rotate` 等 transform,而不是布局属性。
- 最佳实践 2:只导入所需模块以减小 bundle size。
- 最佳实践 3:多个元素动画使用 `stagger`。
- 最佳实践 4:组件卸载时清理动画。
- 最佳实践 5:高频更新使用 `Animatable`。
- 最佳实践 6:复杂序列使用 `timeline`。
- 最佳实践 7:动态动画使用函数式值。
- 最佳实践 8:尊重 `prefers-reduced-motion` 偏好。
- 最佳实践 9:考虑使用 WAAPI bridge 获得原生性能。
- 最佳实践 10:在低性能设备上测试。
适用边界 · 注意事项
- 非 Web/JavaScript 环境或无法引入 Anime.js 的项目不适用。
- 需要 3D/WebGL 或游戏级渲染时,不应仅依赖 Anime.js。
- 已采用其他动画方案且不准备引入 Anime.js 时不必套用。