动画在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相关的知识。
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怎么来实现上面的的动效。
在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的学习。如果您对这方面的知识感兴趣的话,欢迎加入我们,如果你有相关的经验,欢迎在评论中与我们一起分享。
常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。