动画在Web应用中不是必须的,但是使用得好能起到锦上添花的作用。早期在Web中看到的动画主要有Flash、Gif图片动画、JavaScript动画、SVG动画、APNG动画和CSS3动画等。特别是随着浏览器对CSS3属性支持力度的提高,使用CSS3制作动画的情景在Web应用中越来越频繁。
虽然实现动画的技术可以有多种不同的实现方式,但每种技术都存在一定的缺点,比如CSS3动画必须通过JavaScript去获取动态改变的值,setInterval
的时间往往是不精确的而且还会卡顿,APNG动画体积过大等等。
实现方法多意味着实现方式也不同,其中涉及到的技术点也不同,对于Web开发者而言,都希望制作Web动画都具有一套统一的API规则:
值得庆幸的是,W3C提出Web Animation API,它致力于集合CSS3动画的性能,JavaScript的灵活,动画库的丰富等各家所长,将尽可能多的动画控制由原生浏览器实现,并添加许多CSS不具备的变量、控制以及调试选项等。
那么从这篇文章开始,我们将会花几节课的时间和大家一起来探讨Web Animation API相关的知识。
CSS3 Animation
W3C提出的Web Animation API常简称为WAAPI。在开始介绍WAAPI之前,咱们先来回忆一下现在制作动画常用的方法CSS3 Animation。为什么要拿CSS3 Animation出来说呢?因为CSS3 Animation的特性和WAAPI中很多特性非常的类似。
CSS3 Animation中动画最关键的是需要先通过@keyframes
来声明一个动画,然后通过animation-name
来调用@keyframes
声明的动画。不然动画声明、调用之后,还需要触发动画。而触发动画方式主要有文档载入、状态伪类、JavaScript事件等方式来触发。
除此之外,CSS3 Animation除了animation-name
之外,还提供了其它属性来控制动画,比如:
animation-duration
动画持续播放时长animation-delay
动画延迟播放的时长animation-directoin
动画播放方向animation-timing-function
动画播放函数功能animation-fill-mode
动画停留状态animation-iteration-count
动画播放次数animation-play-state
动画播放状态
简单来看W3C官网提供的一张有关于CSS3 Animation属性变化的过程示意图:
我们在这里对CSS3 Animation相关的介绍不做过多的阐述,如果您从未接触过有关于CSS3 Animation相关的知识,建议您先看看这篇文章。
为了后面更好的介绍WAAPI,咱们先来简单的看一个CSS3 Animation动画效果。
@keyframes anime {
0% {
transform: none;
}
25% {
transform: translate(200px, 0);
}
50% {
transform: translate(200px, 200px);
}
75% {
transform: translate(0, 200px);
}
100% {
transform: none;
}
}
然后在需要有动效的元素上调用声明好的动画:
animation: anime 1000ms cubic-bezier(.6, 0, 1, .6) 500ms 50 normal both running;
上面看到的就是通过CSS3 Animation实现的一个简单的动画效果。当然,使用CSS3 Animation还可以实现很多复杂的动效。
前面也说到过,每种实现Web动画技术都存在自己的缺陷,CSS3 Animation也不例外。至于不足之处,这里不多说。有关于CSS3 Animation制作动画先说到这里,咱们来看看WAAPI怎么来实现上面的的动效。
WAAPI入门
在CSS3 Animation和Transition特性还没出来之前,在Web页面中实现一些简单的动效,大家用得比较多的应该是jQuery的.animate()
或者JavaScript中的setTimeout
和setInterval
来实现一些动效。
同样的,在WAAPI中,其核心也是提供了类似于jQuery中的.animate()
一样的一个API:
element.animate(effect, options);
其中element
是指需要有动效的元素,比如上例中的.anime
元素,effect
是一个KeyframeEffects
数组,对应的也就是CSS3 Animation中的@keyframs anime
,另外options
是一个AnimationEffectTimingProperties
参数,对应的是animation-*
属性。
AnimationEffectTimingProperties
对应的animation-*
AnimationEffectTimingProperties | animation-* | 描述 |
---|---|---|
AnimationEffectTimingProperties.delay | animation-delay | 动画延迟播放的时长 |
AnimationEffectTimingProperties.direction | animation-directoin | 动画播放方向 |
AnimationEffectTimingProperties.duration | animation-duration | 动画持续播放时长 |
AnimationEffectTimingProperties.easing | animation-timing-function | 动画播放函数功能 |
AnimationEffectTimingProperties.fill | animation-fill-mode | 动画停留状态 |
AnimationEffectTimingProperties.iterations | animation-iteration-count | 动画播放次数 |
除此之外,WAAPI还提供了AnimationEffectTimingProperties.iterationStart
和AnimationEffectTimingProperties.endDelay
等API。至于这些API怎么使用,先别急。接下来,我们要做的是怎么使用WAAPI来实现上面CSS3 Animation实现的动画效果。
假设我们需要附上动效的元素是
<div class="anime"></div>
根据前面介绍的,需要先选中这个元素,在JavaScript中,可以使用document.querySelector()
:
var eleAnime =document.querySelector('.anime')
选中元素,再调用WAAPI的核心API:
eleAnime.animate(effect, options);
现在关键之处,怎么将effect
和options
调入进去。回忆一下,前面说到过,effect
是一个KeyframeEffects
数组,而options
是一个对象:
eleAnime.animate(
// 对应的是@keyframes
[
{...},
{...}
],
//对应的是animation-*
{
...
}
)
可能有同学会好奇,怎么将CSS Animation中的@keyframes
对应的转换过来,其实很简单,KeyframeEffects
是一个数组,数组里面有多个对象,这里面的每个对象就是对应@keyframes
中的每个帧。这样一来,可以变成:
eleAnime.animate(
// 对应的是@keyframes
[
{
transform: 'none'
},
{
transform: 'translate(200px, 0)'
},
{
transform: 'translate(200px, 200px)'
},
{
transform: 'translate(0, 200px)'
},
{
transform: 'none'
}
],
//对应的是animation-*
{
...
}
)
问题来了,在CSS3 Animation中可以通过类似0%
这样表示对应的帧,那么在WAAPI中如何表达呢?这里需要特别出来,如果在WAAPI中没有显式的设置对应的帧率,那么会将其平均分配。为了能达到更好的效果,WAAPI中提供了一个offset
属性,其值对应的是0~1
,也就对应@keyframes
中的0%~100%
。这样一来,上面的的@keyframes
在WAAPI对应的是:
eleAnime.animate(
// 对应的是@keyframes
[
{
offset: 0,
transform: 'none'
},
{
offset: 0.25,
transform: 'translate(200px, 0)'
},
{
offset: 0.5,
transform: 'translate(200px, 200px)'
},
{
offset: 0.75,
transform: 'translate(0, 200px)'
},
{
offset: 1,
transform: 'none'
}
],
//对应的是animation-*
{
...
}
)
现在完成一半了,还需要添加options
,其实这一步也非常简单:
eleAnime.animate(
// 对应的是@keyframes
[
{
offset: 0,
transform: 'none'
},
{
offset: 0.25,
transform: 'translate(200px, 0)'
},
{
offset: 0.5,
transform: 'translate(200px, 200px)'
},
{
offset: 0.75,
transform: 'translate(0, 200px)'
},
{
offset: 1,
transform: 'none'
}
],
//对应的是animation-*
{
delay: 500,
endDelay: 0,
fill: 'both',
iterationStart: 0,
iterations: 50,
duration: 1000,
direction: 'normal',
easing: 'cubic-bezier(.6, 0, 1, .6)'
}
)
对应的效果如下:
为了方便管理,可以将代码做一上优化:
var eleAnime = document.querySelector('.anime');
var animeKeyframes = [
{
offset: 0,
transform: 'none'
},
{
offset: 0.25,
transform: 'translate(200px, 0)'
},
{
offset: 0.5,
transform: 'translate(200px, 200px)'
},
{
offset: 0.75,
transform: 'translate(0, 200px)'
},
{
offset: 1,
transform: 'none'
}
];
var animeOptions = {
delay: 500,
endDelay: 0,
fill: 'both',
iterationStart: 0,
iterations: 50,
duration: 1000,
direction: 'normal',
easing: 'cubic-bezier(.6, 0, 1, .6)'
};
eleAnime.animate(animeKeyframes,animeOptions);
除了使用上面的方法之外,在WAAPI中还有另一种方式:
new Animation(effect, timeline)
这种方法和前面的略有不同,要让动画生效,需要配合WAAPI中的new keyframeEffect(element, keyframeSet, keyframeOptions)
和.play()
方法。这样一来,上面的示例可以改成:
var eleAnime = document.querySelector('.anime');
var animeKeyframes = {
transform: ['none', 'translate(200px, 0)', 'translate(200px, 200px)', 'translate(0, 200px)', 'none']
};
var animeOptions = {
delay: 500,
endDelay: 0,
fill: 'both',
iterationStart: 0,
iterations: 50,
duration: 1000,
direction: 'normal',
easing: 'cubic-bezier(.6, 0, 1, .6)'
};
var effect = new KeyframeEffect(eleAnime, animeKeyframes, animeOptions);
var animation = new Animation(effect, eleAnime.ownerDocument.timeline);
animation.play();
效果如下:
特别提示,使用这种方式,目前支持的浏览器较少,要想在浏览器看到有效果,需要引入一个polyfill。
<script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.2.1/web-animations-next.min.js"></script>
效果看到,我们来看下面的效果,是CSS Animation和WAAPI实现的效果:
总结
文章主要介绍了WAAPI入门相关的知识点,通过WAAPI两种不同方式来实现动效。上面涉及到的只是WAAPI上的皮毛知识点,主要让大家通过简单的实例对WAAPI有一个初步的认识,以及对比其实现动效和CSS3有何不同之处和相似之处。后面我们将继续深入的学习有关于WAAPI相关的其他知识点,因为这套原生的动画API能帮我实现更好的动效。
虽然现在浏览器对WAAPI的支持力度还不是很强,但我们应该深信,随着时间的推移,一定会得到完美的支持。尽管还未得到很好的支持,但并不影响我们对WAAPI的学习。如果您对这方面的知识感兴趣的话,欢迎加入我们,如果你有相关的经验,欢迎在评论中与我们一起分享。
如需转载,烦请注明出处:http://www.w3cplus.com/animation/waapi-basic-intro.html