Web Animations API 教程
简介
Web Animations API (WAAPI) 是一个提供给 JavaScript 开发者用于创建和控制网页动画的接口。它结合了 CSS 动画和 JavaScript 动画的优点,提供了一个高性能且易于使用的动画解决方案。
主要优势
- 性能优化:直接使用浏览器的动画引擎,与 CSS 动画性能相当
- 精确控制:提供比 CSS 更精细的动画控制能力
- 动态性:可以根据用户交互或其他条件动态生成和调整动画
- 统一标准:提供一个标准化的 API,减少对第三方库的依赖
基本概念
Web Animations API 主要由以下几个核心概念组成:
- Element.animate() - 创建动画的主要方法
- KeyframeEffect - 定义动画变化的关键帧
- Animation - 提供控制动画播放的接口
- AnimationTimeline - 控制动画的时间线
创建简单动画
使用 Element.animate()
方法可以快速创建一个基本动画:
const element = document.querySelector('.box');
// 创建一个简单的移动动画
const animation = element.animate(
[
// 关键帧
{ transform: 'translateX(0px)' },
{ transform: 'translateX(300px)' }
],
{
// 动画配置
duration: 1000, // 持续时间(毫秒)
easing: 'ease-in-out', // 动画缓动函数
delay: 0, // 延迟时间
iterations: Infinity, // 重复次数(无限循环)
direction: 'alternate', // 方向(交替)
fill: 'forwards' // 填充模式(保持最终状态)
}
);
控制动画
Animation
对象提供了多种方法来控制动画的播放状态:
// 暂停动画
animation.pause();
// 继续播放
animation.play();
// 反向播放
animation.reverse();
// 取消动画
animation.cancel();
// 完成动画(跳到结束)
animation.finish();
// 设置动画速度
animation.playbackRate = 2; // 2倍速播放
你还可以获取动画的各种状态:
// 获取当前播放状态
console.log(animation.playState); // 'running', 'paused', 'finished', 'idle'
// 检查动画是否正在播放
console.log(animation.pending);
// 获取当前播放时间
console.log(animation.currentTime);
动画时间轴
时间轴控制动画的时间流向:
// 获取当前动画时间
const currentTime = animation.currentTime;
// 设置动画时间(跳转到特定位置)
animation.currentTime = 500; // 跳转到500毫秒处
关键帧格式
关键帧可以通过多种方式定义:
数组对象格式
element.animate([
{ opacity: 0, transform: 'scale(0.5)' }, // 起始帧
{ opacity: 0.5, transform: 'scale(0.75)' }, // 中间帧
{ opacity: 1, transform: 'scale(1)' } // 结束帧
], 1000);
带偏移量的对象
element.animate({
opacity: [0, 0.5, 1],
transform: ['scale(0.5)', 'scale(0.75)', 'scale(1)'],
offset: [0, 0.7, 1] // 指定每个关键帧的时间点
}, 1000);
使用 KeyframeEffect
const keyframes = new KeyframeEffect(
element,
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' }
],
{ duration: 1000, fill: 'forwards' }
);
const animation = new Animation(keyframes, document.timeline);
animation.play();
动画事件
你可以监听动画的各种事件:
// 动画开始
animation.onfinish = () => {
console.log('动画结束了!');
};
// 使用 Promise 方式
animation.finished.then(() => {
console.log('动画完成!');
}).catch(() => {
console.log('动画被取消');
});
// 监听动画取消
animation.oncancel = () => {
console.log('动画被取消');
};
高级应用
时序组合
使用 GroupEffect
可以组合多个动画:
// 注意:GroupEffect 仍处于实验阶段,可能需要使用 polyfill
const moveEffect = new KeyframeEffect(
boxElement,
{ transform: ['translateX(0)', 'translateX(300px)'] },
{ duration: 1000, fill: 'forwards' }
);
const fadeEffect = new KeyframeEffect(
boxElement,
{ opacity: [1, 0] },
{ duration: 1000, fill: 'forwards' }
);
// 创建组效果
const groupEffect = new GroupEffect([moveEffect, fadeEffect]);
const animation = new Animation(groupEffect, document.timeline);
animation.play();
创建可复用的动画模板
function createFadeAnimation(element, duration = 1000) {
return element.animate(
[
{ opacity: 0 },
{ opacity: 1 }
],
{
duration: duration,
fill: 'forwards'
}
);
}
// 使用模板创建多个动画
const elements = document.querySelectorAll('.item');
elements.forEach((el, index) => {
const anim = createFadeAnimation(el);
// 延迟开始
anim.startTime = document.timeline.currentTime + (index * 100);
});
浏览器兼容性
Web Animations API 现已在大多数现代浏览器中得到支持。对于旧版浏览器,可以使用 web-animations-js polyfill。
// 检测浏览器支持
if (!Element.prototype.animate) {
console.log('浏览器不支持 Web Animations API,需要使用 polyfill');
}
与CSS动画对比
特性 | Web Animations API | CSS 动画 |
---|---|---|
性能 | 非常好(与CSS相当) | 非常好 |
控制能力 | 强大,可编程控制 | 有限,需通过JS间接控制 |
动态生成 | 方便,原生JS支持 | 需要生成或修改CSS |
复杂度 | 中等 | 简单 |
兼容性 | 需要polyfill | 广泛支持 |
性能优化
使用 Web Animations API 时的性能最佳实践:
-
尽量只动画 transform 和 opacity 属性
这些属性可以在合成器线程上执行,不会触发布局和绘制。
-
避免频繁修改动画参数
频繁修改动画参数可能导致主线程阻塞。
-
使用
will-change
提前告知浏览器.animated-element { will-change: transform, opacity; }
-
在必要时取消不可见元素的动画
if (!elementIsVisible) { animation.cancel(); }
实例项目
示例1:图片轮播
const slides = document.querySelectorAll('.slide');
let currentSlide = 0;
function rotateSlides() {
// 当前幻灯片退出
slides[currentSlide].animate(
[
{ opacity: 1, transform: 'translateX(0)' },
{ opacity: 0, transform: 'translateX(-100px)' }
],
{ duration: 500, fill: 'forwards' }
);
// 更新当前幻灯片索引
currentSlide = (currentSlide + 1) % slides.length;
// 新幻灯片进入
slides[currentSlide].animate(
[
{ opacity: 0, transform: 'translateX(100px)' },
{ opacity: 1, transform: 'translateX(0)' }
],
{ duration: 500, fill: 'forwards' }
);
}
// 每3秒切换一次
setInterval(rotateSlides, 3000);
示例2:自定义路径动画
// 定义一个复杂的运动路径
function animateAlongPath(element, duration = 2000) {
return element.animate([
{ offset: 0, transform: 'translate(0, 0)' },
{ offset: 0.25, transform: 'translate(100px, 0)' },
{ offset: 0.5, transform: 'translate(100px, 100px)' },
{ offset: 0.75, transform: 'translate(0, 100px)' },
{ offset: 1, transform: 'translate(0, 0)' }
], {
duration: duration,
easing: 'ease-in-out',
iterations: Infinity
});
}
const box = document.querySelector('.moving-box');
const pathAnimation = animateAlongPath(box);
// 用户控制
document.querySelector('#speed-control').addEventListener('input', (e) => {
pathAnimation.playbackRate = e.target.value;
});
示例3:顺序动画
async function sequentialAnimation() {
const element = document.querySelector('.animated-element');
// 第一个动画:旋转
const rotate = element.animate(
[
{ transform: 'rotate(0deg)' },
{ transform: 'rotate(360deg)' }
],
{ duration: 1000, fill: 'forwards' }
);
// 等待第一个动画完成
await rotate.finished;
// 第二个动画:缩放
const scale = element.animate(
[
{ transform: 'scale(1)' },
{ transform: 'scale(1.5)' },
{ transform: 'scale(1)' }
],
{ duration: 1000, fill: 'forwards' }
);
// 等待第二个动画完成
await scale.finished;
// 第三个动画:移动
return element.animate(
[
{ transform: 'translateY(0)' },
{ transform: 'translateY(100px)' },
{ transform: 'translateY(0)' }
],
{ duration: 1000, fill: 'forwards' }
);
}
// 启动顺序动画
sequentialAnimation().then(() => {
console.log('所有动画序列完成!');
});
总结
Web Animations API 为开发者提供了一个标准化、高性能且灵活的动画创建方式。它结合了 CSS 动画的性能和 JavaScript 动画的可编程性,特别适合需要精确控制或复杂动画逻辑的场景。
随着浏览器支持度的提高,Web Animations API 正在成为前端动画开发的重要工具。在合适的项目中使用它,可以帮助我们创建流畅、高效的网页动画效果,提升用户体验。