Web Animations 与 Angular动画
什么是Web Animations
概述
正如CSS Animations一样,Web Animations是javascript提供的一组动画接口,它允许同步和定时更改网页的呈现, 即DOM元素的动画。因此,使用Web Animations可以方便地用Js操作动画,而不再需要像之前那样写一大堆css和定时器来实现。
兼容性
它目前尚属W3C的标准草案,详情可查阅:https://www.w3.org/TR/web-animations/ ,因此很多浏览器并不能完整支持,
正因如此,W3C官方为开发者提供了web-animations/web-animations-js polyfill插件,是我们能通过插件来解决浏览器的支持问题,插件地址:https://github.com/web-animations/web-animations-js/tree/master
1 | <script src="web-animations.min.js"></script> |
如上所示插入插件,即可使用Web Animations进行开发。
代码示例
提供了很简洁明了的,我们可以在 dom 元素上直接调用的 animate 函数:
1 | var element = document.querySelector('.animate-me'); |
第一个参数是一个对象数组,每个对象表示动画中的一帧:
1 | var keyframes = [ |
这与 css 中的 keyframe 定义类似:
1 | 0% { |
第二个参数是 duration,表示动画的时间。同时也支持在第二个参数中传入配置项来指定缓动方式、循环次数等:
1 | var options = { |
在 dom 元素上调用 animate 函数之后返回一个 Animation 对象,或者通过 ele.getAnimation 方法获取 dom 上的 Animation 对象。
Animation对象有一些属性和方法,比如:
Animation.finished(此动画的当前完成的状态,只读)Animation.effect(与此动画相关联的关键帧)Animation.play()(开始播放动画)Animation.pause()(暂停播放动画)
等等。
Animation对象还有两个事件处理程序:
Animation.oncancel:获取并设置取消事件的事件处理程序Animation.onfinish:获取并设置完成事件的事件处理程序
由以上API,开发者可以通过 promise 和 event 两种方式对动画进行操作:
1 | // 通过监听事件进行处理 |
1 | // 通过承诺进行处理 |
与CSS动画相比的优点
低耦合
CSS 动画中,如果需要控制动画或者过渡的开始或结束只能通过相应的 dom 事件来监听,并且在回调函数中操作,这也是受 CSS 本身语言特性约束所致。也就是说很多情况下,想要完成一个动画需要结合 CSS 和 JS 来共同完成。使用 WAAPI 则有 promise 和 event 两种方式与监听 dom 事件相对应。从代码可维护性和完整性上看 WAAPI 有自身语言上的优势。
兼容性和流畅度
事实上Web Animations常用方法现在已经兼容了大部分现代的浏览器。如果想现在就玩玩,可以使用官方提供的polyfill。而CSS动画我们也用了很久,基本上对于老旧的浏览器只能用一些优雅的降级方案。至于流畅度的问题两者性能差距不大,而且Web Animations提供了性能优化的方案。
Angular中的Web Animations动画
概述,及引入方法
Angular动画是基于标准的Web动画API(Web Animations API)构建的,它们在支持此API的浏览器中会用原生方式工作。
上述是官方文档对于Angular动画的解释。由于基于Web Animations,因此很多写法也是非常相像的。
和http、form一样,Angular中的动画也是一个独立模块,首先需在根模块进行导入:
1 | import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; |
就在组件里去定义动画了,如果需要定义大量的动画片段,建议单独建立一个项目的动画模块。当然,定义动画之前需要引入一些常用的API:
1 | import { trigger, state, style, transition, animate, keyframes } from '@angular/animations'; |
基本写法
1 | import { |
上述代码在@Component元数据中构建了一个名为clickAnim的简单动画,它会让<h1>元素在两个状态active和inactive之间转场, 当处于active激活状态时,它会把该元素显示得稍微大一点、亮一点。模板中用[@triggerName]语法即可调用。

状态(state)
在此动画中,我们可以为每个动画状态定义了一组样式:
1 | state('inactive', style({ |
这些state具体定义了每个状态的最终样式,也就是说,这里其实并不只是在定义动画,而是在定义该元素在不同状态时应该具有的样式。
除了自定义状态,还有两种特殊状态:
- void:匹配尚未被添加进来或者已经被移除了的状态,用于进场或离场动画
- *:匹配任何动画的状态
transition()
而负责这定义两组样式转换的则是transition()函数,它的第一个参数负责定义需被转换的状态名称(可定义多个):
1 | transition('inactive => active', animate('100ms ease-in')), |
其中,=> 也可以写成 <=> 即双向的。
第二个参数是一个animate()函数或一个数组,负责定义动画执行的总时间以及样式,当有些样式只希望在动画过程中生效,结束后并不保留,可以在数组中定义一个style()函数:
1 | transition('inactive => active', [ |
关键帧
上述代码中,关于动画运行的方式,用了ease-in和ease-out两种方法,除此之外还有几种,例如linear等,同CSS动画一样,甚至可以使用一些赛贝尔曲线,例如cubic-bezier(0.4, 0, 0.2, 1)。我们可以在这两个网站自定义挑选赛贝尔曲线的表达式:
同CSS一样,并不是所有的赛贝尔曲线都能被使用的,所以关键帧的设置必不可少,它在Angular中是这样写的:
1 | transition('* => void', [ |
上述代码是一个典型的“离场动画”,它在第二帧定义了一些“反弹”效果。
offset属性定义了此帧在整个动画中处于哪个时间点,它并不一定用绝对数字定义,而是在0到1之间的相对值(百分比),而且它是可选的,如果省略它,偏移量会自动根据帧数平均分布出来。
第三方动画库
上述的动画我们直接写在了组件中,更多时候往往需要把它们抽象出来,形成一个自己的动画库,可以在各个组件调用。下面这个简单的库来自于segmentfault社区:
1 | // animate.ts |
上述代码定义了8种常用动画效果,还可以自定义time变量修改动画速度。在使用时,可以在组件直接全部引入:
1 | import { simAnim } from './animate.ts'; |
亦或是单独引入某个动画:
1 | import { fadeIn } from './animate.ts'; |
然后在组件元数据中加入动画数组:
1 | ({ |
然后在模板中加入:<div @flyIn @flyOut>...</div>,也可以写成<div [@simAnim]="'flyIn'">...</div>
如果上述代码仍不满足需求,可以引入其它开源项目,比如:https://github.com/jiayihu/ng-animate
它是一个更强大的开源项目,动画演示及说明文档非常详细,这里就不再赘述。

