使用Web Animations API建立炫酷动画

如何优雅地用原生 JS 写动画?相信 WAAPI 能够帮到您。javascript

11-23-54.jpg

Web Animations API

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 能在绝大部分浏览器运行。数组

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 动画的区别:

  • WAAPI 不须要明确地告知每一个关键帧出现的时刻在动画中的百分比,它将根据您给出的关键帧数量自动将动画划分为相等的部分。当咱们想要明确地设置一个关键帧与其余关键帧的偏移量时,咱们能够直接在对象中指定一个偏移量( offset:大小范围是 0 ~ 1 )。
  • WAAPI 的关键帧对象中,须要使用元素属性的驼峰写法,例如对应 CSS 的属性 "margin-Left" , WAAPI 的关键帧对象要使用 "marginLeft" 。
  • WAAPI 必须至少指定两个关键帧( 表示动画序列的开始和结束状态 )。若是您的关键帧对象数组只有一个对象成员, Element.animate() 将抛出不支持的异常报错。

动画效果属性的对象

咱们还须要建立一个动画效果属性的对象 ( 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 无对应属性 规定在迭代过程当中动画的开始时间点。
  • easing 的默认值是 linear,而 animation-timing-function 的默认值是 ease。在使用 WAAPI 时应使用恰当的 easing ,以避免让动画变得机械和乏味( 默认的 linear 表示动画从头至尾的速度是相同的 )。
  • animation-iteration-count 对应的是 iterations。若是你想要让动画一直重复下去,请使用 Infinity 代替 infinite。注意 Infinity 不须要使用逗号包裹,它是 JavaScript 的一个关键字,而其余值是字符串。
  • 时间单位使用 ms 替代了 s,这对于写过 JavaScript 的开发者来讲会更容易接受。( 实际上在 CSS 动画中也可以使用 ms,不过基本没人会这样用。)
  • endDelay 表示动画结束后的延迟时间,与 delay 的默认值都为0。若是要将多个动画串在一块儿,可是但愿在一个动画的结尾和任何后续动画的开始之间存在时间间隔,就可使用 endDlay。
  • iterationStart 表示在迭代过程当中动画的开始时间点。E.g. 若是 iterations 设置为 1,而且 iterationStart 设置为 0.5,动画将从中间开始播放到动画结尾,而后从动画开头开始,结束于中间。而若是将 iterations 和 iterationStart 都设置为 0.5,动画将从中间开始播放到结尾就结束了。

建立完以上所说的“关键帧对象的数组”和“动画效果属性的对象” ,就能够简单地启动一个动画了。能够在文章后面查看具体实例。

element.animate( slidingLeft, animateOptions );

咱们想学会如何去控制使用 WAAPI 建立的动画,仍须要了解 Animation 对象。

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 :

  • oncancel :定义动画被取消时或执行 cancel() 时触发的回调函数。
  • onfinish :定义动画天然完成播放时或执行finish() 时触发的回调函数。

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 定义的动画:
image.png

WAAPI 实例 —— 轮播图

看懂了上面提到的知识,咱们就可使用 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 来实现一样的动画效果。

参考资料

相关文章
相关标签/搜索