Web Animations API 教程

Web Animations API 教程

简介

Web Animations API (WAAPI) 是一个提供给 JavaScript 开发者用于创建和控制网页动画的接口。它结合了 CSS 动画和 JavaScript 动画的优点,提供了一个高性能且易于使用的动画解决方案。

主要优势

  • 性能优化:直接使用浏览器的动画引擎,与 CSS 动画性能相当
  • 精确控制:提供比 CSS 更精细的动画控制能力
  • 动态性:可以根据用户交互或其他条件动态生成和调整动画
  • 统一标准:提供一个标准化的 API,减少对第三方库的依赖

基本概念

Web Animations API 主要由以下几个核心概念组成:

  1. Element.animate() - 创建动画的主要方法
  2. KeyframeEffect - 定义动画变化的关键帧
  3. Animation - 提供控制动画播放的接口
  4. 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 APICSS 动画
性能非常好(与CSS相当)非常好
控制能力强大,可编程控制有限,需通过JS间接控制
动态生成方便,原生JS支持需要生成或修改CSS
复杂度中等简单
兼容性需要polyfill广泛支持

性能优化

使用 Web Animations API 时的性能最佳实践:

  1. 尽量只动画 transform 和 opacity 属性

    这些属性可以在合成器线程上执行,不会触发布局和绘制。

  2. 避免频繁修改动画参数

    频繁修改动画参数可能导致主线程阻塞。

  3. 使用 will-change 提前告知浏览器

    .animated-element {
      will-change: transform, opacity;
    }
    
  4. 在必要时取消不可见元素的动画

    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 正在成为前端动画开发的重要工具。在合适的项目中使用它,可以帮助我们创建流畅、高效的网页动画效果,提升用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值