如何优雅地用原生 JS 写动画?相信 WAAPI 能够帮到您。javascript
Web Animations API ( Web 动画 API,简称 WAAPI )可让咱们用 JavaScript 写动画而且控制动画。
这些 API 被设计成 CSS Animations 和 CSS Transitions的接口。将来会对这些 API 作补充使其功能更强大,它是对网络上动画化的支持最有效的方式之一。
经过 Web 动画 API ,咱们能够将交互式动画从样式表移动到 JavaScript,将表现与行为分开。 咱们再也不须要依赖 DOM,如将 CSS 属性和范围类写入元素来控制播放方向。 与纯粹的声明式 CSS 不一样,JavaScript 还容许咱们动态地将属性值设置为持续时间。 对于构建自定义动画库和建立交互式动画,Web 动画 API 多是完成工做的完美工具。css
简单实例:WAAPI 实现轮播图java
当咱们谈及网页动画时,天然联想到的是 CSS3 动画、JS 动画、SVG 动画、APNG 动画等技术以及 jQuery.animate() 等动画封装库,根据实际动画内容设计去选择不一样的实现方式。git
然而,每一个现行的动画技术都存在必定的缺点,如 CSS3 动画必须经过JS去获取动态改变的值,setInterval 的时间每每是不精确的并且还会卡顿,APNG 动画会带来文件体积较大的困扰,引入额外的动画封装库也并不是对性能敏感的业务适用。目前情形对开发者而言,鱼和熊掌彷佛不可兼得,既但愿得到更强大便捷的动画控制能力,又但愿性能和体验上足够流畅优雅,若是能有一种浏览器原生支持的通用的动画解决方案,那将是极好极好的呢。github
W3C 提出 Web Animation API(简称WAAPI)正缘于此,它致力于集合 CSS3 动画的性能、JavaScript 的灵活、动画库的丰富等各家所长,将尽量多的动画控制由原生浏览器实现,并添加许多 CSS 不具有的变量、控制以及或调的选项。web
Firefox 48+ 和 Chrome 36+ 中提供了对 WAAPI 功能的支持。 Webkit 和 Edge 已经将 WAAPI 移动到各自的待办事项列表中。能够在 Can I Use 上查看完整的浏览器支持状况.api
WAAPI 有一个完善且强大的 polyfill 外部库,使得咱们如今能够在生产环境下使用它,即使是在浏览器受限的状况下。web-animations.min.js 使 WAAPI 能在绝大部分浏览器运行。数组
element.animate( keyframes, AnimationEffectTimingProperties );
keyframes:关键帧对象的数组
AnimationEffectTimingProperties:动画效果属性的对象浏览器
E.g.网络
document.getElementById("elementId").animate( [ { transform: 'rotate(0)', color: '#000' }, { transform: 'rotate(360deg)', color: '#fff' } ], { duration: 3000, iterations: Infinity } );
WAAPI 的基本语法和 jQuery 的 .animate() 十分类似。但 WWAPI 是浏览器原生支持的,不用引入外部库,在性能上也有很大的优点。接下来咱们一步一步地学习 WAAPI 的用法。
使用 WAAPI,首先要作的是建立一个相似于 CSS3 @keyframes 的关键帧对象数组。
E.g. 建立一个轮播图滑动动画的关键帧对象数组
var slidingLeft = [ //经过 margin-left 和 opacity的渐变来实现简单滑动 { marginLeft: '0px', opacity: 1 }, { opacity: 0.6, offset: 0.7 }, { marginLeft: "-5rem", opacity: 1 } ];
Web 动画 API 和 CSS3 动画的区别:
咱们还须要建立一个动画效果属性的对象 ( AnimationEffectTimingProperties object )。
E.g.
var animateOptions = { duration: 1500, easing: 'ease-in-out', }
须要注意的是,AnimationEffectTimingProperties 有一些专业的术语与咱们熟悉的 CSS3 animation 属性有所不一样。
下表是二者的对应关系。
AnimationEffectTimingProperties | CSS3 animation 属性 | 简述 |
---|---|---|
duration | animation-duration | 规定动画完成一个周期所花费的秒或毫秒。默认是 0。 |
easing | animation-timing-function | 规定动画的速度曲线。 |
delay | animation-delay | 规定动画什么时候开始。默认是 0。 |
iterations | animation-iteration-count | 规定动画被播放的次数。默认是 1。 |
direction | animation-direction | 规定动画是否在下一周期逆向地播放。默认是 'normal' 。 |
fill | animation-fill-mode | 规定动画在播放以前或以后,其动画效果是否可见。 |
endDelay | 无对应属性 | 规定动画结束后的延迟时间。 |
iterationStart | 无对应属性 | 规定在迭代过程当中动画的开始时间点。 |
建立完以上所说的“关键帧对象的数组”和“动画效果属性的对象” ,就能够简单地启动一个动画了。能够在文章后面查看具体实例。
element.animate( slidingLeft, animateOptions );
咱们想学会如何去控制使用 WAAPI 建立的动画,仍须要了解 Animation 对象。
animate 方法不只仅能让元素使用动画,它还有本身的返回值 —— 一个 Animation 对象。经过改变这个对象的属性和调用它的方法,便可优雅地去控制这个动画。
var animationObj = element.animate(keyframes, AnimationEffectTimingProperties );
Animation 对象具备的属性:
属性名 | 意义 |
---|---|
currentTime | 动画的当前时间值,以毫秒为单位。若是缺乏 timeline,则其值为 null,即表示动画不活动或还没有播放。 |
effect | 动画的目标效果。能够是基于 AnimationEffectReadOnly 的类型的效果对象,例如 KeyframeEffect 或 null 。 |
finished | 只读。返回此动画完成后执行的 Promise 对象。 |
id | 标识动画的字符串。 |
playState | 只读。动画的播放状态,常见的有 running, paused, finished 。 |
playbackRate | 动画的播放速度,默认值为 1。当值为 0.5 时动画会减慢一半,当值为负值时动画会反向播放 |
ready | 只读。返回当前动画准备好播放时执行的 Promise 对象。 |
startTime | 动画播放开始时的预约时间。默认为 null。能够更改此值以使动画在不一样的时间开始。 |
timeline | 与当前动画相关联的时间轴。默认与文档的时间轴相同。 |
Animation 对象具备的方法:
方法名 | 用途 |
---|---|
cancel() | 清除由此动画形成的全部关键帧效果,并停止其播放。 |
finish() | 将当前播放时间设置为与当前播放方向相对应的动画结束时间。若为正常播放,则把当前播放时间设置为动画总时长;若为反向播放则把当前播放时间设置为0。 |
pause() | 暂停播放动画 |
play() | 开始或继续播放动画。若是动画已完成,则再次开始播放动画。 |
reverse() | 将动画的播放方向反转。若是在未播放的动画上调用,动画将从结尾向开头反向播放。 若是对暂停中的动画进行了调用,动画将向反方向继续播放。一样的效果能够经过设置 playbackRate *= -1; 来实现 |
Animation 对象的事件处理程序(回调函数):
WWAPI 支持使用 event 和使用 Promise 两种方式来处理事件。
下面是两种 event :
E.g. 若是一个动画被取消了,移除其元素。
animation.oncancel = animation.effect.target.remove();
Promise
Promise 对象用于一个异步操做的最终完成(或失败)及其结果值的表示。
animation 对象的 ready 和 finished 属性会返回一个 Promise 对象,分别对应在动画准备播放和播放结束的时候。下面是一个使用 Promise 来处理事件回调的示例:
myAnimation.finished.then(() => element.remove())
document.getAnimations() 方法返回当前有效的全部Animation对象的数组,此数组包括CSS Animation,CSS Transition 和 Web Animation。
在较新版本的 Chrome 浏览器的开发者工具(F12)的 console drawer 中还能查看页面中全部的 Animation,包括用 CSS3 定义的动画:
看懂了上面提到的知识,咱们就可使用 WWAPI 来实现一个简单的轮播图,点击打开 codepen 预览并查看完整代码。
JS 部分代码:
var indexBody = document.querySelector(".index_body"); var btnLeft = document.querySelector(".left_btn"); var btnRight = document.querySelector(".right_btn"); var slideBox = document.querySelector('.slidebox'); var items = slideBox.getElementsByClassName("slide_item"); //使用web animations建立动画,左滑和右滑共用一个动画 var slidingLeft = [ {marginLeft: '0px', opacity: 1}, {opacity: 0.6, offset: 0.7}, {marginLeft: "-5rem", opacity: 1} ]; var sliding = slideBox.animate( slidingLeft, { duration: 1500, easing: 'ease-in-out', } ); sliding.onfinish = function(){ slideBox.style.marginLeft = '0px'; if(sliding.playbackRate != -1){ slideBox.appendChild(items[0]); } btnRight.onclick = slideRight; btnLeft.onclick = slideLeft; }; function slideRight(){ sliding.playbackRate = 1; //切换滑动方向为右 sliding.play(); btnLeft.onclick = null; btnRight.onclick = null; // console.log(sliding.effect); }; function slideLeft(){ slideBox.insertBefore(items[items.length - 1],items[0]); slideBox.style.marginLeft = '-5rem'; sliding.playbackRate = -1; //切换滑动方向为左 sliding.play(); btnLeft.onclick = null; btnRight.onclick = null; }; btnRight.onclick = slideRight; btnLeft.onclick = slideLeft; //自动滑动 var slideTimer = setInterval(() => { btnRight.click(); },3000); //鼠标悬停时中止滑动 indexBody.onmouseover = function(){ clearInterval(slideTimer); }; //鼠标离开时继续自动滑动 indexBody.onmouseout = function(){ slideTimer = setInterval(() => { btnRight.click(); },3000); };
web-animations 官方的 demo 很是适合初接触WAAPI的同窗做为开始的范例。
另外推荐一个挺炫酷的动画库 —— Animista,上面有不少用 CSS3 实现的动画(可在线查看代码,主要是 keyframes ),咱们能够尝试用 WWAPI 来实现一样的动画效果。