848 字
2 分钟
Anime.js 完全指南:轻量级 JavaScript 动画引擎的现代化应用
🎬 什么是 Anime.js?
Anime.js 是一个轻量级、功能强大的 JavaScript 动画引擎,能够处理 CSS 属性、SVG、DOM 元素和 JavaScript 对象的动画。它提供了一个统一的 API 来处理 Web 上的各种动画需求,是目前最受欢迎的动画库之一。
为什么选择 Anime.js?
1. 极致轻量与高性能
// 文件大小:仅 18KB (gzipped: 6KB)// 无依赖,加载速度极快import anime from 'animejs'2. 统一的 API 设计
// 同一个 API 可以动画化不同的目标anime({ targets: '.css-selector', // CSS 选择器 targets: '#myElement', // DOM 元素 targets: nodeList, // 节点列表 targets: object, // JavaScript 对象 translateX: 250})3. 强大的时间轴系统
// 复杂的动画序列轻松管理const timeline = anime.timeline({ easing: 'easeOutExpo', duration: 750}).add({ targets: '.box', translateX: 250}).add({ targets: '.circle', translateY: 100})4. 丰富的缓动函数
内置了 30+ 种缓动函数,让动画更加自然流畅。
🚀 快速开始
安装配置
# npmnpm install animejs --save
# yarnyarn add animejs
# pnpmpnpm add animejs
# CDN 直接引入<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>第一个动画
<!DOCTYPE html><html><head> <title>Anime.js 入门</title> <style> .box { width: 100px; height: 100px; background-color: #1a73e8; border-radius: 8px; } </style></head><body> <div class="box"></div>
<script type="module"> import anime from 'animejs'
// 创建动画 anime({ targets: '.box', translateX: 250, rotate: '1turn', backgroundColor: '#e91e63', duration: 2000, easing: 'easeInOutQuad' }) </script></body></html>✨ 炫酷示例展示
看下面这个动画效果,只需要几行代码就能实现:
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});
这个动画展示了 Anime.js 的几个强大特性:
- 交错效果(stagger):从中心向外扩散的延迟动画
- 多重属性:同时动画化位置和旋转
- 循环播放:无限循环且来回播放
- 缓动函数:平滑的运动轨迹
📚 核心概念与API
基础动画参数
anime({ targets: '.element', // 动画目标 translateX: 250, // 动画属性 translateY: 100, backgroundColor: '#FF5722', duration: 1000, // 持续时间 (毫秒) delay: 500, // 延迟时间 endDelay: 200, // 结束延迟 easing: 'easeInOutQuad', // 缓动函数 round: 1, // 数值精度 direction: 'alternate', // 方向:normal, reverse, alternate loop: true, // 循环播放 autoplay: true, // 自动播放})动画属性支持
CSS 属性动画
anime({ targets: '.css-element', // 几何属性 left: '50%', top: '100px', width: '200px', height: '200px', // 变换属性 translateX: '50%', translateY: '50%', scale: 2, rotate: '1turn', skewX: '20deg', // 颜色属性 color: '#FFF', backgroundColor: '#FF5722', borderColor: '#00BCD4'})SVG 动画
// SVG 路径动画anime({ targets: 'path', strokeDashoffset: [anime.setDashoffset, 0], easing: 'easeInOutSine', duration: 1500, direction: 'alternate', loop: true})
// SVG 变换anime({ targets: '.svg-shape', translateX: 100, rotate: 180, scale: 1.5, fill: '#FF5722'})JavaScript 对象动画
// 动画化 JavaScript 对象const progress = { percent: 0 }
anime({ targets: progress, percent: 100, easing: 'linear', update: function() { console.log(`Progress: ${Math.round(progress.percent)}%`) }})🎯 高级特性
1. 时间轴(Timeline)
const tl = anime.timeline({ easing: 'easeOutExpo', duration: 750})
// 添加动画到时间轴tl.add({ targets: '.box-1', translateX: 250, backgroundColor: '#FF5722'}).add({ targets: '.box-2', translateY: 100, backgroundColor: '#4CAF50'}, '-=500') // 提前 500ms 开始.add({ targets: '.box-3', translateX: 250, translateY: 100, backgroundColor: '#2196F3'})2. 交错动画(Staggering)
// 网格交错动画anime({ targets: '.grid-item', scale: [ {value: .1, easing: 'easeOutSine', duration: 500}, {value: 1, easing: 'easeInOutQuad', duration: 1200} ], delay: anime.stagger(100, {grid: [14, 5], from: 'center'})})
// 简单交错anime({ targets: '.stagger-item', translateX: 250, delay: anime.stagger(100) // 每个元素延迟 100ms})
// 复杂交错模式anime({ targets: '.item', scale: [.5, 1], delay: anime.stagger(200, { from: 'last', // 从最后一个开始 direction: 'reverse', // 反向交错 grid: [5, 3], // 网格布局 easing: 'easeInQuad' // 交错缓动 })})3. 关键帧动画
// 多阶段动画anime({ targets: '.keyframe-element', keyframes: [ {translateX: 100, backgroundColor: '#FF5722'}, {translateY: 100, backgroundColor: '#4CAF50'}, {translateX: 0, backgroundColor: '#2196F3'}, {translateY: 0, backgroundColor: '#FF9800'} ], duration: 2000, easing: 'easeInOutQuad'})
// 复杂关键帧序列anime({ targets: '.complex-element', keyframes: [ {value: 100, duration: 500}, {value: 0, duration: 1000, easing: 'easeInOutSine'}, {value: 200, duration: 800, easing: 'easeInOutQuad'}, {value: 50, duration: 600, easing: 'easeInOutCubic'} ]})4. 播放控制
const animation = anime({ targets: '.playback-element', translateX: 250, duration: 2000, autoplay: false // 禁用自动播放})
// 播放控制document.querySelector('#play').addEventListener('click', animation.play)document.querySelector('#pause').addEventListener('click', animation.pause)document.querySelector('#restart').addEventListener('click', animation.restart)
// 跳转到特定时间document.querySelector('#seek').addEventListener('click', () => { animation.seek(1000) // 跳转到 1000ms})
// 反向播放document.querySelector('#reverse').addEventListener('click', () => { animation.reverse()})
// 设置播放速度animation.speed = 2 // 2倍速5. 回调函数
anime({ targets: '.callback-element', translateX: 250, duration: 2000,
// 动画开始前 begin: function(anim) { console.log('Animation started') },
// 动画完成时 complete: function(anim) { console.log('Animation completed') },
// 每一帧更新时 update: function(anim) { console.log(`Progress: ${anim.progress}%`) },
// 动画运行时 run: function(anim) { console.log('Animation is running') },
// 动画暂停时 pause: function(anim) { console.log('Animation paused') }})🔥 实战应用示例
1. 加载动画
<div class="loader"> <div class="dot"></div> <div class="dot"></div> <div class="dot"></div></div>
<style>.loader { display: flex; gap: 10px;}.dot { width: 20px; height: 20px; background-color: #1a73e8; border-radius: 50%;}</style>
<script>// 加载动画anime({ targets: '.dot', scale: [ {value: .1, easing: 'easeOutSine', duration: 500}, {value: 1, easing: 'easeInOutQuad', duration: 1200} ], delay: anime.stagger(200, {from: 'first'}), loop: true, direction: 'alternate', easing: 'easeInOutSine'})</script>2. 页面过渡效果
// 页面切换动画function pageTransition() { const tl = anime.timeline({ easing: 'easeInOutExpo', duration: 750 })
// 当前页面淡出 tl.add({ targets: '.current-page', opacity: 0, translateY: -50, duration: 500 }) // 新页面淡入 .add({ targets: '.new-page', opacity: [0, 1], translateY: [50, 0], duration: 500 }, '-=250')}
// 导航菜单动画anime({ targets: '.nav-item', translateX: [-100, 0], opacity: [0, 1], delay: anime.stagger(100, {from: 'first'}), easing: 'easeOutExpo'})3. 数据可视化动画
// 图表动画function animateChart() { // 柱状图动画 anime({ targets: '.bar', height: (el) => el.dataset.value, delay: anime.stagger(100), easing: 'easeOutQuart', duration: 1500 })
// 数字增长动画 const counter = {value: 0}
anime({ targets: counter, value: 1000, round: 1, easing: 'easeOutExpo', duration: 2000, update: function() { document.querySelector('.counter').textContent = counter.value.toLocaleString() } })}4. 交互式动画
// 鼠标跟随效果document.addEventListener('mousemove', (e) => { anime({ targets: '.cursor-follower', left: e.clientX, top: e.clientY, duration: 500, easing: 'easeOutQuad' })})
// 点击波纹效果document.querySelector('.button').addEventListener('click', function(e) { const ripple = document.createElement('span') ripple.classList.add('ripple') this.appendChild(ripple)
const x = e.clientX - e.target.offsetLeft const y = e.clientY - e.target.offsetTop
anime({ targets: ripple, left: x, top: y, scale: [0, 4], opacity: [1, 0], duration: 600, easing: 'easeOutExpo', complete: () => ripple.remove() })})5. 滚动触发动画
// 滚动动画触发const observerOptions = { threshold: 0.2, rootMargin: '0px'}
const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { // 元素进入视口时触发动画 anime({ targets: entry.target, translateY: [100, 0], opacity: [0, 1], duration: 800, easing: 'easeOutQuart' })
observer.unobserve(entry.target) } })}, observerOptions)
// 观察需要动画的元素document.querySelectorAll('.animate-on-scroll').forEach(el => { observer.observe(el)})🎨 高级技巧
1. 性能优化
// 使用 transform 和 opacityanime({ targets: '.performant-element', transform: 'translateX(200px) scale(1.5)', opacity: .5, duration: 1000})
// 避免动画 width、height、margin 等属性// ❌ 不推荐anime({ targets: '.element', width: '200px', height: '200px'})
// ✅ 推荐anime({ targets: '.element', transform: 'scale(2)'})2. 响应式动画
// 根据屏幕尺寸调整动画参数function getResponsiveValue(mobile, tablet, desktop) { const width = window.innerWidth if (width < 768) return mobile if (width < 1024) return tablet return desktop}
anime({ targets: '.responsive-element', translateX: getResponsiveValue(100, 200, 300), scale: getResponsiveValue(1.2, 1.5, 2), duration: getResponsiveValue(800, 1200, 1500)})3. 动画链式调用
// Promise 链式调用async function complexAnimation() { await anime({ targets: '.step-1', translateX: 250, duration: 1000 }).finished
await anime({ targets: '.step-2', translateY: 100, duration: 800 }).finished
await anime({ targets: '.step-3', scale: 1.5, backgroundColor: '#FF5722', duration: 600 }).finished
console.log('所有动画完成!')}🌟 最佳实践
1. 合理使用缓动函数
// 不同场景使用不同的缓动anime({ targets: '.element', translateX: 250, easing: 'easeInOutQuad' // 入场和退场动画})
anime({ targets: '.bounce-element', translateY: [-100, 0], easing: 'easeOutBounce' // 弹跳效果})
anime({ targets: '.smooth-element', scale: [0, 1], easing: 'easeOutExpo' // 平滑缩放})2. 避免过度动画
// ❌ 不好的做法 - 过度使用动画anime({ targets: '.every-element', rotate: '1turn', scale: [1, 1.2, 1], backgroundColor: ['#FF5722', '#4CAF50', '#2196F3'], duration: 3000})
// ✅ 好的做法 - 有目的的动画anime({ targets: '.important-element', translateX: 250, duration: 600, easing: 'easeOutQuart'})3. 使用 requestAnimationFrame
// Anime.js 内部使用 requestAnimationFrame// 但你也可以手动控制const animation = anime({ targets: '.element', translateX: 250, autoplay: false})
// 手动控制每一帧function customLoop() { animation.tick() if (!animation.paused) { requestAnimationFrame(customLoop) }}
customLoop()🆚 Anime.js vs 其他动画库
与 GSAP 对比
| 特性 | Anime.js | GSAP |
|---|---|---|
| 文件大小 | 18KB | ~90KB |
| 学习曲线 | 🟢 平缓 | 🟡 适中 |
| 时间轴系统 | ✅ 基础 | ✅ 强大 |
| 插件生态 | ⚠️ 有限 | ✅ 丰富 |
| 性能 | ✅ 优秀 | ✅ 优秀 |
| 适用场景 | 轻量动画 | 复杂项目 |
选择建议
- 选择 Anime.js:轻量级项目、简单动画、预算有限
- 选择 GSAP:复杂时间轴、高级功能、商业项目
📊 实际项目案例
1. Hero 区域动画
// 首页 Hero 动画序列function heroAnimation() { const tl = anime.timeline({ easing: 'easeOutExpo' })
tl.add({ targets: '.hero-title', translateY: [50, 0], opacity: [0, 1], duration: 1000 }) .add({ targets: '.hero-subtitle', translateY: [30, 0], opacity: [0, 1], duration: 800 }, '-=500') .add({ targets: '.hero-cta', scale: [0, 1], opacity: [0, 1], duration: 600 }, '-=400') .add({ targets: '.hero-visual', translateX: [50, 0], opacity: [0, 1], rotate: [10, 0], duration: 1200 }, '-=800')}2. 产品展示动画
// 产品特性展示function showcaseFeatures() { anime({ targets: '.feature-card', translateY: [100, 0], opacity: [0, 1], delay: anime.stagger(150, { grid: [3, 2], from: 'first' }), duration: 800, easing: 'easeOutQuart' })}🚀 性能优化技巧
1. 使用 CSS 变换
// ✅ 使用 transform (GPU 加速)anime({ targets: '.element', translateX: '200px', scale: 1.5, rotate: '45deg'})
// ❌ 避免使用布局属性anime({ targets: '.element', left: '200px', width: '200px'})2. 批量操作
// ✅ 批量动画anime({ targets: '.multiple-elements', translateX: 100})
// ❌ 避免循环创建动画document.querySelectorAll('.element').forEach(el => { anime({ targets: el, translateX: 100 })})3. 合理使用 will-change
.optimized-element { will-change: transform, opacity;}🎓 总结
Anime.js 是一个功能强大且易于使用的动画库,特别适合:
- ✅ 轻量级动画需求
- ✅ 快速原型开发
- ✅ 学习动画编程
- ✅ 性能敏感项目
- ✅ 移动端应用
核心优势
- 🎯 简单易学:统一的 API 设计
- ⚡ 性能优秀:轻量级且高效
- 🎨 功能全面:支持各种动画需求
- 🔄 时间轴系统:复杂序列轻松管理
- 📱 响应式友好:适配各种设备
使用建议
- 简单项目:直接使用 Anime.js
- 复杂动画:考虑时间轴功能
- 性能优先:使用 transform 属性
- 交互体验:合理使用缓动函数
TIP开始使用 Anime.js 的最佳时机:
- 需要 UI 动画效果
- 希望提升用户体验
- 追求轻量级解决方案
- 学习动画编程基础
相关阅读:
有问题? 欢迎在评论区讨论你的 Anime.js 使用经验!
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
Anime.js 完全指南:轻量级 JavaScript 动画引擎的现代化应用
https://basyc.cloud/posts/animejs-guide/ 部分信息可能已经过时
相关文章 智能推荐




