关于 anime-js
面向 Anime.js、JavaScript 和 Web 动画开发的指导技能,提供动画编排、性能优化与无障碍实践。适合实现交互动画及 React 动画组件的开发者。
主要功能
- 01时间线与交错动画
- 02SVG 路径动画与形变
- 03缓动与动态取值
- 04React 集成指导
- 05性能与减少动态效果建议
适用场景
- 01编排多元素动画序列
- 02制作 SVG 路径动画
- 03实现 React 组件动效
- 04适配减少动态效果偏好
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mindrally/ skills --skill anime-js安装后在 Claude Code 中输入/anime-js确认已加载。
详细介绍
Anime.js 动画指南
你是 Anime.js、JavaScript 和 Web 动画性能方面的专家。创建动画时请遵循以下指南。
核心原则
安装和导入
npm install animejs
// Full import
import anime from "animejs";
// Modular import for smaller bundle size
import { animate, timeline, stagger } from "animejs";
基本动画
anime({
targets: ".element",
translateX: 250,
rotate: "1turn",
duration: 800,
easing: "easeInOutQuad"
});
性能优化
帧率控制
// Adjust global frame rate for lower-end devices
anime.suspendWhenDocumentHidden = true;
// Control FPS for specific animations
anime({
targets: ".element",
translateX: 250,
update: function(anim) {
// Custom frame rate limiting if needed
}
});
优先使用变换属性,而非布局属性
// Good - uses GPU-accelerated transforms
anime({
targets: ".element",
translateX: 100, // Good
translateY: 50, // Good
scale: 1.2, // Good
rotate: 45, // Good
opacity: 0.5 // Good
});
// Avoid - causes layout recalculation
anime({
targets: ".element",
left: 100, // Avoid
top: 50, // Avoid
width: 200, // Avoid
height: 150 // Avoid
});
高频更新使用 Animatable
import { Animatable } from "animejs";
// Optimized for continuous updates (mouse tracking, etc.)
const animatable = new Animatable(".cursor", {
x: 0,
y: 0
});
document.addEventListener("mousemove", (e) => {
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",
translateY: [30, 0],
opacity: [0, 1]
}, "-=500") // Overlap by 500ms
.add({
targets: ".footer",
translateY: [30, 0],
opacity: [0, 1]
}, "-=500");
时间线控制
const tl = anime.timeline({
autoplay: false
});
// Control methods
tl.play();
tl.pause();
tl.restart();
tl.reverse();
tl.seek(1000); // Go to 1 second
交错动画
基本交错动画
anime({
targets: ".grid-item",
translateY: [50, 0],
opacity: [0, 1],
delay: anime.stagger(100) // 100ms delay between each
});
高级交错选项
// Stagger from center
anime({
targets: ".grid-item",
scale: [0, 1],
delay: anime.stagger(100, { from: "center" })
});
// Grid stagger
anime({
targets: ".grid-item",
scale: [0, 1],
delay: anime.stagger(50, {
grid: [14, 5],
from: "center"
})
});
// Stagger with easing
anime({
targets: ".item",
translateX: 250,
delay: anime.stagger(100, { easing: "easeOutQuad" })
});
缓动函数
内置缓动函数
// Common easings
anime({
targets: ".element",
translateX: 250,
easing: "easeOutExpo" // Fast start, slow end
// easing: "easeInOutQuad" // Smooth both ends
// easing: "easeOutElastic(1, .5)" // Bouncy
// easing: "easeOutBounce" // Bounce effect
// easing: "spring(1, 80, 10, 0)" // Physics-based
});
自定义缓动
anime({
targets: ".element",
translateX: 250,
easing: "cubicBezier(0.25, 0.1, 0.25, 1)"
});
SVG 动画
路径动画
const path = anime.path(".motion-path");
anime({
targets: ".element",
translateX: path("x"),
translateY: path("y"),
rotate: path("angle"),
easing: "linear",
duration: 2000,
loop: true
});
描边绘制
anime({
targets: "path",
strokeDashoffset: [anime.setDashoffset, 0],
easing: "easeInOutSine",
duration: 1500,
delay: anime.stagger(250)
});
变形
anime({
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"
});
基于函数的值
动态值
anime({
targets: ".element",
translateX: function(el, i) {
return i * 100; // Each element moves further
},
rotate: function(el, i, total) {
return (360 / total) * i; // Distribute rotation
},
delay: function(el, i) {
return i * 50;
}
});
回调和事件
动画事件
anime({
targets: ".element",
translateX: 250,
begin: function(anim) {
console.log("Animation started");
},
update: function(anim) {
console.log(Math.round(anim.progress) + "%");
},
complete: function(anim) {
console.log("Animation completed");
}
});
循环
anime({
targets: ".element",
translateX: 250,
direction: "alternate",
loop: true,
loopComplete: function(anim) {
console.log("Loop completed");
}
});
React 集成
React 基本用法
import { useEffect, useRef } from "react";
import anime from "animejs";
function AnimatedComponent() {
const elementRef = useRef(null);
useEffect(() => {
const animation = anime({
targets: elementRef.current,
translateX: 250,
duration: 800
});
return () => {
animation.pause(); // Cleanup
};
}, []);
return <div ref={elementRef}>Animated</div>;
}
使用 useCallback 控制
function ControlledAnimation() {
const elementRef = useRef(null);
const animationRef = useRef(null);
const playAnimation = useCallback(() => {
animationRef.current = anime({
targets: elementRef.current,
translateX: [0, 250],
duration: 800
});
}, []);
useEffect(() => {
return () => {
animationRef.current?.pause();
};
}, []);
return (
<>
<div ref={elementRef}>Animated</div>
<button onClick={playAnimation}>Play</button>
</>
);
}
Web Animations API 桥接
使用 WAAPI 获得原生性能
import { wapiAnimate } from "animejs";
// Uses browser's native Web Animations API
wapiAnimate(".element", {
translateX: 250,
duration: 800
});
无障碍
尊重减少动态效果的偏好
const prefersReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
anime({
targets: ".element",
translateX: 250,
duration: prefersReducedMotion ? 0 : 800,
easing: prefersReducedMotion ? "linear" : "easeOutExpo"
});
最佳实践总结
- 优先使用变换属性(translate、scale、rotate),而非布局属性
- 只导入所需模块,以减小打包体积
- 多个元素的动画使用交错效果
- 组件卸载时清理动画
- 高频更新使用 Animatable
- 复杂序列使用时间线
- 动态动画使用基于函数的值
- 尊重减少动态效果的偏好
- 考虑使用 WAAPI 桥接来获得原生性能
- 在性能较低的设备上测试
评论
支持 Markdown