动画


再也不能用定时器做动画

CSS动画

CSS动画是浏览器原生支持的动画实现方式,具有以下特点:

  1. 硬件加速:浏览器会自动优化,使用GPU加速

  2. 流畅度高:由浏览器内部调度,与刷新率同步

  3. 简单易用:只需定义关键帧和动画属性

  4. 性能优异:不会阻塞主线程

1
2
3
4
5
6
7
8
.box {
animation: move 2s ease-in-out infinite;
}

@keyframes move {
0% { transform: translateX(0); }
100% { transform: translateX(100px); }
}

JS动画

计时器动画(setTimeout/setInterval)

使用计时器实现动画存在严重问题:

  1. 时间不精准

    • 受事件循环机制影响,回调可能被延迟执行
    • 最小间隔时间受限(通常4ms)
  2. 帧率不稳定

    • 无法与屏幕刷新率同步
    • 可能导致动画卡顿或跳帧
  3. 性能问题

    • 即使页面不可见也会继续执行
    • 增加不必要的CPU负担
1
2
3
4
5
6
7
// 不推荐的实现方式
let pos = 0;
const timer = setInterval(() => {
pos += 1;
element.style.left = pos + 'px';
if(pos >= 100) clearInterval(timer);
}, 16); // 试图模拟60fps

requestAnimationFrame (RAF)

RAF是专为动画设计的API,特点包括:

  1. 与刷新率同步

    • 自动匹配显示器刷新率(通常60fps)
    • 每次重绘前调用回调函数
  2. 高效节能

    • 页面不可见时自动暂停
    • 浏览器可以优化执行
  3. 更流畅的动画

    • 避免过度渲染
    • 减少不必要的计算
1
2
3
4
5
6
7
function animate() {
element.style.left = (pos += 1) + 'px';
if(pos < 100) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);

Web Animations API

现代浏览器提供的强大动画API:

  1. 声明式语法

    1
    2
    3
    4
    5
    6
    7
    8
    element.animate([
    { transform: 'translateX(0)' },
    { transform: 'translateX(100px)' }
    ], {
    duration: 1000,
    easing: 'ease-in-out',
    iterations: Infinity
    });
  2. 优势特性

    • 与CSS动画相同的性能优势
    • 提供精细控制(暂停、反转、变速等)
    • 可以监听动画事件
    • 返回Animation对象便于控制
  3. 时间轴控制

    1
    2
    3
    4
    const animation = element.animate(/* ... */);
    animation.pause(); // 暂停
    animation.play(); // 播放
    animation.cancel(); // 取消

最佳实践建议

  1. 优先使用CSS动画:简单动画首选CSS实现

  2. 复杂动画使用Web Animations API:需要程序控制时选择

  3. 必要时使用RAF:需要完全控制动画流程时

  4. 避免使用定时器动画:性能差且不精准

现代浏览器提供了多种高性能动画方案,开发者应该摒弃传统的定时器动画方式,选择更高效、更精准的动画实现技术。