本期精读文章 [CSS Animations vs Web Animations API | CSS-Tricks](https://css-tricks.com/css-animations-vs-web-animations-api/)

译文地址 [CSS Animation 与 Web Animation API 之争](https://zhuanlan.zhihu.com/p/27867539?refer=FrontendMagazine)

# 1. 引言

<img src="https://img.alicdn.com/imgextra/i3/O1CN01O88KwS1bcAxfZER9N_!!6000000003485-2-tps-1438-583.png" alt="logo" width="500" />

前端是一个很神奇的工种，一个合格的前端至少要熟练的使用 3 个技能，html、css 和 javascript。在传统的前端开发领域它们三个大多时候是各司其职，分别负责布局、样式以及交互。而在当代的前端开发中，由于多种原因 javascript 做的事情愈来愈多，大有一统全栈之势。服务端的 nodejs，让前端同学可以用自己的语言来开发 server。即便是在前端，我们现在好像也很少写 html 了，在 React 中出来了 JSX，在其他的开发体系中也有与之类似的前端模板代替了 html。我们好像也很少写 css 了，sass、less、stylus 等预处理器以及 css in js 出现。此外，很多 css 领域的的工作也可以通过 javascript 以更加优雅和高效的方式实现。今天我们来一起聊聊 CSS 动画与 WEB Animation API 的优劣。

# 2. 内容概要

JavaScript 规范确实借鉴了很多社区内的优秀类库，通过原生实现的方式提供更好的性能。WAAPI 提供了与 jQuery 类似的语法，同时也做了很多补充，使得其更加的强大。同时 W3C 官方也为开发者提供了 [web-animations/web-animations-js](https://github.com/web-animations/web-animations-js/tree/master) polyfill。下面简单回顾下文章内容：

WAAPI 提供了很简洁明了的，我们可以直接在 dom 元素上直接调用 animate 函数：

```javascript
var element = document.querySelector('.animate-me');
var animation = element.animate(keyframes, 1000);
```

第一个参数是一个对象数组，每个对象表示动画中的一帧：

```javascript
var keyframes = [
  { opacity: 0 },
  { opacity: 1 }
];
```

这与 css 中的 keyframe 定义类似：

```css
0% {
  opacity: 0;
}
100% {
  opacity: 1;
}
```

第二个参数是 duration，表示动画的时间。同时也支持在第二个参数中传入配置项来指定缓动方式、循环次数等。

```javascript
var options = {
  iterations: Infinity, // 动画的重复次数，默认是 1
  iterationStart: 0, // 用于指定动画开始的节点，默认是 0
  delay: 0, // 动画延迟开始的毫秒数，默认 0
  endDelay: 0, // 动画结束后延迟的毫秒数，默认 0
  direction: 'alternate', // 动画的方向 默认是按照一个方向的动画，alternate 则表示交替
  duration: 700, // 动画持续时间，默认 0
  fill: 'forwards', // 是否在动画结束时回到元素开始动画前的状态
  easing: 'ease-out', // 缓动方式，默认 "linear"
};
```

有了这些配置项，基本可以满足开发者的动画需求。同时，文中也提到了在 WAAPI 中很多专业术语与 CSS 变量有所不同，不过这些变化也更显简洁。

在 dom 元素上调用 animate 函数之后返回 animation 对象，或者通过 ele.getAnimation 方法获取 dom 上的 animation 对象。借此开发者可以通过 promise 和 event 两种方式对动画进行操作：

## 1. event 方式

```javascript
myAnimation.onfinish = function() {
  element.remove();
}
```

## 2. promise 方式

```javascript
myAnimation.finished.then(() =>
  element.remove())
```

通过这种方式相对 dom 事件获取更加的简洁优雅。

# 3. 精读

参与本次精度的同学主要来自 [前端外刊评论 - 知乎专栏](https://zhuanlan.zhihu.com/FrontendMagazine) 的留言，该部分主要由文章评论总结而出。

## WAAPI 优雅简洁

web animation 的 api 设计优雅而又全面。文中比对了常见的 WAAPI 与 CSS Animation 对照关系，我们可以看到 WAAPI 更加简洁，而且语法上也更加容易为开发者接受。确实，在写一些复杂的动画逻辑时，需要灵活控制性强的接口。我们可以看到，在处理串连多个动画、截取完整动画的一部分时更加方便。如果非要说有什么劣势，个人在开发中感觉 keyframe 的很多只都只能使用字符串，不过这也是将 css 写在 js 中最常见的一种方式了。

## 低耦合

CSS 动画中，如果需要控制动画或者过渡的开始或结束只能通过相应的 dom 事件来监听，并且在回调函数中操作，这也是受 CSS 本身语言特性约束所致。也就是说很多情况下，想要完成一个动画需要结合 CSS 和 JS 来共同完成。使用 WAAPI 则有 promise 和 event 两种方式与监听 dom 事件相对应。从代码可维护性和完整性上看 WAAPI 有自身语言上的优势。

## 兼容性和流畅度

兼容性上 WAAPI 常用方法已经兼容了大部分现代的浏览器。如果想现在就玩玩 WAAPI，可以使用官方提供的 polyfill。而 CSS 动画我们也用了很久，基本作为一种在现代浏览器中提升体验的方式，对于老旧的浏览器只能用一些优雅的降级方案。至于流畅度的问题，文中也提到性能与 CSS 动画一般，而且提供了性能优化的方案。

# 4. 总结

目前看来，CSS 动画可以做到的，使用 WAAPI 同样可以实现。至于浏览器支持问题，WAAPI 尚需要 polyfill 支持，不过 CSS 动画也同样存在兼容性问题。可能现在新的 API 的接受度还不够，但正如文章结尾处所说：『现有的规范和实现看起来更像是一项伟大事业的起点。』

> 讨论地址是：[精读《CSS Animations vs Web Animations API》 · Issue #22 · dt-fe/weekly](https://github.com/dt-fe/weekly/issues/22)
>
> 如果你想参与讨论，请[点击这里](https://github.com/dt-fe/weekly)，每周都有新的主题，每周五发布。
