WAAPI动画

Web Animations API,WAAPI 允许同步和定时更改网页的呈现, 即DOM元素的动画。它通过组合两个模型来实现:时序模型动画模型

概念

WAAPI将浏览器动画引擎向开发者打开,并由JavaScript进行操作。这些API被设计成 CSS Animations and CSS Transitions的接口,未来会对这些API做补充以丰富更多的功能。它是对网络上动画化的支持最有效的方式之一,让浏览器进行自己的内部,不需要hacks,或者强迫,或者Window.requestAnimationFrame()。

通过Web动画API,我们可以将交互式动画从样式表移动到JavaScript,将表现与行为分开。 我们不再需要依赖DOM重的技术,如将CSS属性和范围类写入元素来控制播放方向。 与纯粹的声明式CSS不同,JavaScript还允许我们动态地将属性值设置为持续时间。 对于构建自定义动画库和创建交互式动画,WAAPI可能是完成工作的完美工具。

性能表现

WAAPI 有着和 CSS 动画一样的性能表现,虽然这不意味着你可以毫无顾忌的使用动画。

从CSS动画过渡到WAAPI

假如我们有这样一个css动画:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.a-demo {
animation: demorun infinite 3s linear;
}

@keyframes demorun {
0% {
color: #000;
transform: rotate(0) translate3D(-50%, -50%, 0);
}
30% {
color: #431236;
}
100% {
color: #000;
transform: rotate(360deg) translate3D(-50%, -50%, 0);
}
}

动画很简单,接着改为WAAPI:
首先要做的是创建一个对应于我们的CSS @keyframes块的关键帧对象

1
2
3
4
5
var demoTumbling = [
{ transform: 'rotate(0) translate3D(-50%, -50%, 0)', color: '#000' },
{ color: '#431236', offset: 0.3},
{ transform: 'rotate(360deg) translate3D(-50%, -50%, 0)', color: '#000' }
];

这里我们使用一个包含多个对象的数组。 每个对象代表原始CSS中的一个键。 然而,与CSS不同,Web动画API不需要明确地告知每个键出现的动画的百分比。 它将根据您给出的按键数量自动将动画划分为相等的部分。

当我们想要明确地设置一个键与其他键的偏移量时,我们可以直接在对象中指定一个偏移量,并与逗号分隔。如上第2个键。

注意,必须至少指定两个关键帧(表示动画序列的开始和结束状态).如果您的关键帧列表只有一个条目, Element.animate() 将抛出不支持的异常报错.

接着,创建表示时间属性

1
2
3
4
var demoTiming = {
duration: 3000,
iterations: Infinity
}

它与CSS的表示有所差异:

  • 持续时间是毫秒ms,而不是秒s
  • 线性方式是easing,而不是animation-timing-function
  • 播放次数是iterations, 而不是 animation-iteration-count

最后,整合这些特性

1
2
3
4
document.getElementById("demo").animate(
demoTumbling,
demoTiming
)

即:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<p id="demo" style="width: 70px; height: 70px; background-color: red">123</p>

<script>
var demoTumbling = [
{ color: 'blue', transform: 'rotate(0) translate3D(-50%, -50%, 0)' },
{ color: '#fff' },
{ color: 'red', transform: 'rotate(360deg) translate3D(-50%, -50%, 0)' },
];
var demoTiming = {
duration: 3000,
iterations: Infinity
};

var animate = document.getElementById('demo').animate(demoTumbling, demoTiming);
console.log(animate)
</script>

上面定义将返回一个Animation对象。其中Element.animate()中时间属性可以为Number。

Animation构造函数

语法

1
var animation = new Animation(effect, timeline);

其中:

  • effect: 可选。
    将KeyframeEffect对象分配给动画。(在将来,其他类型的效果,如SequenceEffects或GroupEffects是可能被实现的,但现在,唯一的效果是KeyframeEffect。)
  • timeline: 可选。
    指定与动画关联的时间轴。默认为Document.timeline。 这也可以设置为null。

如:

1
var rabbitDownAnimation = new Animation(rabbitDownKeyframes, document.timeline);

Animation实例属性

  • Animation.currentTime:动画的当前时间值(以毫秒为单位),无论是正在运行还是已暂停。 如果动画缺少timeline或尚未播放,其值为null。
  • Animation.effect:实验属性,
    获取或设置与此动画相关联的KeyframeEffect。
  • Animation.finished: 实验属性,只读。返回此动画的当前完成的状态。
  • Animation.id。获取或设置用于标识动画的字符串。
  • Animation.playState: 只读。返回描述动画播放状态的枚举值。
  • Animation.playbackRate:返回或设置动画的播放速率。
  • Animation.ready:实验属性,只读。返回此动画的当前就绪状态。
  • Animation.startTime:获取或设置动画播放应开始的预定时间。
  • Animation.timeline:实验属性。获取或设置与此动画相关联的timeline。

Animation实例事件处理

Animation方法

  • Animation.cancel():实验方法,清除此动画的所有keyframeEffects,并中止播放。
  • Animation.finish():实验方法,设置动画中止播放。
  • Animation.pause():实验方法,暂停播放动画。
  • Animation.play():实验方法,开始或恢复播放动画,或者如果之前完成,则重新开始动画。
  • Animation.reverse():实验方法,反转播放动画,直到播放到动画开始时停止。 如果动画完成或未播放,它将从头到尾播放。

具体兼容情况请见后文。

动画控制

将CSS动画转为js并不是WAAPI最强大的地方,它真正厉害的是操纵动画的播放。Web动画API提供了一些控制播放的有用方法:play(),pause(),reverse()和playbackRate。

暂停pause()和启动play()

假如我们定义了这样一个动画

1
2
3
4
5
6
7
8
9
var demoAnimate = document.getElementById('demo').animate(
[
{ transform: 'translateY(0)' },
{ transform: 'translateY(-80%)' }
], {
fill: 'forwards',
easing: 'steps(4, end)',
duration: aliceChange.effect.timing.duration / 2
});

Element.animate() 方法会在调用后立即执行。不过我们可以通过调用 Animation.pause()暂停动画。

1
demoAnimate.pause();

然后我们可以在我们想播放的时候调用Animation.play()播放动画。

1
demoAnimate.play();

其他控制方法

除了暂停和播放,我们可以使用以下动画方法:

  • Animation.finish() 动画结束.
  • Animation.cancel() 终止动画.
  • Animation.reverse() 设置动画播放速度
  • Animation.playbackRate,控制动画播放速率,负值可将动画倒放。如animate.playbackRate = -1

兼容情况

原生WAAPI的兼容情况很是不好,如图所示
compatibility.png

现在也有个页面可以用来检测当前浏览器环境WAAPI各属性方法的兼容情况:https://codepen.io/danwilson/pen/xGBKVq/

不兼容的环境下使用WAAPI

现在已经有完善的polyfill-web-animations-js,使得我们现在可以在生产环境下使用它。

使用非常简单,如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- Include the polyfill -->
<script src="web-animations.min.js"></script>

<!-- Set up a target to animate -->
<div class="pulse" style="width: 150px;">Hello world!</div>

<!-- Animate! -->
<script>
var elem = document.querySelector('.pulse');
var animation = elem.animate({
opacity: [0.5, 1],
transform: ['scale(0.5)', 'scale(1)'],
}, {
direction: 'alternate',
duration: 500,
iterations: Infinity,
});
</script>

当然,在不支持WAAPI的浏览器上动画的执行是通过DOM,这样的性能不如CSS3动画。

其他

个人目前WAAPI的优势还不是很明显,主要是兼容的原因,其次CSS动画的控制问题我们也可以通过DOM操作弥补。不过作为较为新兴的API我们可以实现了解。WAAPI的动画控制很像视频控制或者是lottie,个人认为统一的控制形式会受到更多开发者的支持。


相关链接