当咱们谈及网页动画时,天然联想到的是 CSS3 动画、JS 动画、SVG 动画 等技术以及 jQuery.animate() 等动画封装库,根据实际动画内容设计去选择不一样的实现方式,然而,每一个现行的动画技术都存在必定的缺点,如 CSS3动画必须经过JS去获取动态改变的值,一个动画效果分散在css文件和js文件里很差维护,setInterval 的时间每每是不精确的并且还会卡顿,引入额外的动画封装库也并不是对性能敏感的业务适用。javascript
Web Animation API 的历史也应该有几年了,可是每当作动画效果时,笔者就是依赖各类库,不多想着去原生实现,最终形成了咱们的项目各类依赖库,体积也不断变大,性能如何也不得而知,做为前端开发的咱们多么但愿原生的JS去支持通用的动画解决方案, Web Animation API 可能就是一个不错的解决方案。css
W3C 提出 Web Animation API(简称 WAAPI)正缘于此,它致力于集合 CSS3 动画的性能、JavaScript 的灵活、动画库的丰富等各家所长,将尽量多的动画控制由原生浏览器实现,并添加许多 CSS 不具有的变量、控制以及或调的选项。它为咱们提供了一种通用语言来描述DOM元素的动画,主要方法有:Animation,KeyframeEffect,AnimationEvent,DocumentTimeline,EffectTiming。关于这个API的详细介绍,能够参照MDN的这篇文档,连接地址:developer.mozilla.org/en-US/docs/…html
使用Web Animations API,咱们能够将交互式动画从样式表移动到JavaScript,将表示与行为分开。咱们再也不须要依赖DOM的技术,例如编写CSS属性做用于元素以控制方向。为了构建自定义动画库和建立交互式动画,Web Animations API多是完成工做的完美工具,你无需借助第三方动画库,就能够轻松实现一个效果不错的动画。前端
为了让你们对这个API有个清晰的认识,笔者在接下来的系列文章里,用五六个例子让你们理解这个API,今天笔者将用此API实现一个随机移动的图片开始进行介绍,好比用这个效果咱们能够制做一个随机飘浮移动的广告位,游戏里随机走动的怪物等等,本例中的特色就是为了体现Web Animation API的灵活性和强大性,我没有引用任何第三方类库,好比(JQ)以及也没有使用setTimeout和requestAnimationFrame()函数。java
本篇文章预计时间 5 分钟git
开始前,咱们先来看看完成后的动画效果,示例以下效果:github
不管图片怎么随机移动,咱们都但愿在指定的容器里,而不是漫无边际,首先咱们在html页面定义容器:web
<div id="container"> </div>复制代码
接下来定义容器的样式:数组
body { margin: 0; } div#container { height:500px; width:100%; background: #C6CEF7; } #target { position: absolute; filter: drop-shadow(-12px 12px 7px rgba(0,0,0,0.5)); }复制代码
var container = document.getElementById("container");复制代码
为了更加直观性,我选择一个走动的gif图片,因为图片的加载须要一些时间,为了避免破坏动画的连贯性,确保图片加载完了咱们在执行动画,相关代码以下:浏览器
var target = document.createElement("img");
target.id = "target";
target.onload = function() {
floatHead();
}
target.src = "walk.gif";
container.appendChild(target);复制代码
你们都看到了,onload部分咱们加载了floatHead()函数,接下来咱们来进行相关实现,此函数主要包含如下功能:建立一个随机位置,计算移动时间,封装移动动画。
咱们利用Math.floor函数实现了其随机位置的变化,示例代码以下:
function makeNewPosition() {
var containerVspace = container.offsetHeight - target.offsetHeight,
containerHspace = container.offsetWidth - target.offsetWidth,
newX = Math.floor(Math.random() * containerVspace),
newY = Math.floor(Math.random() * containerHspace);
return [newX, newY];
}复制代码
这里的随机位置,咱们返回了一个数组,描述的是图片相对容器的位置,即top,left。这里你须要理解offsetHeight,offsetWidth,可理解为div的可视高度或宽度,样式的height或Width+上下padding或左右padding+上下border-width或左右border-width。
动画是有时间属性的,咱们进行位置的移动,须要花多久时间,假设运动速度为0.1个单位/毫秒。这个函数包含两个数组:prev为当前目标的原始X和Y位置,next为移动目标的位置。此函数没有进行进行精确的距离计算,只是判断了x和y轴上移动的距离大小用最大的距离除以速度,示例代码以下:
function velocity(prev, next) {
var x = Math.abs(prev[1] - next[1]),
y = Math.abs(prev[0] - next[0]),
larger = x > y ? x : y,
speedModifier = 0.1,
time = Math.ceil(larger / speedModifier);
return time;
}复制代码
接下来是咱们Web Animations API的核心部分,咱们使用其核心API在加上上述咱们完成的两个函数让其动起来,示例代码以下:
function floatHead() {
var newPos = makeNewPosition(),
oldTop = target.offsetTop,
oldLeft = target.offsetLeft,
target.animate([
{ top: oldTop+"px", left: oldLeft+"px" },
{ top: newPos[0]+"px", left: newPos[1]+"px" }
], {
duration: velocity([oldTop, oldLeft],newPos),
fill: "forwards"
}).onfinish = function() {
floatHead();
}
}复制代码
该Animation的animate函数有两个参数,一个是KeyframeEffects数组和AnimationEffectTimingPropertiesoptions 的对象。基本上,第一个参数映射到您将放入CSS中的内容@keyframes,你能够想象成css中的@keyframes内容,好比如下代码:
@keyframes emphasis {
0% {
transform: scale(1);
opacity: 1;
}
30% {
transform: scale(.5);
opacity: .5;
}
78.75% {
transform: scale(.667);
opacity: .667;
}
100% {
transform: scale(.6);
opacity: .6;
}
}复制代码
你能够将“{}”里的信息顺序依次放到一个数组里;第二个参数是时间控制 timing,包括有 duration 持续时间、iterations 执行次数、direction 动画方向、easing 缓动函数等属性。好比如下代码:
#toAnimate {
animation: emphasis 700ms ease-in-out 10ms infinite alternate forwards;
}复制代码
你还可能注意到咱们使用了onfinish事件完成了floatHead函数的反复调用,其是Animation的属性,监听动画完成事件,若是动画完成继续执行floatHead(),至关不断的递归调用。
<!DOCTYPE html> <html lang="en"> <head> <style> body { margin: 0; } div#container { height:500px; width:100%; background: #C6CEF7; } #target { position: absolute; filter: drop-shadow(-12px 12px 7px rgba(0,0,0,0.5)); } </style> <meta charset="UTF-8"> <title>前端达人示例展现——图片随机移动</title> </head> <body> <div id="container"></div> <script> function makeNewPosition() { var containerVspace = container.offsetHeight - target.offsetHeight, containerHspace = container.offsetWidth - target.offsetWidth, newX = Math.floor(Math.random() * containerVspace), newY = Math.floor(Math.random() * containerHspace); return [newX, newY]; } function velocity(prev, next) { var x = Math.abs(prev[1] - next[1]), y = Math.abs(prev[0] - next[0]), larger = x > y ? x : y, speedModifier = 0.2, time = Math.ceil(larger / speedModifier); return time; } function floatHead() { var newPos = makeNewPosition(), oldTop = target.offsetTop, oldLeft = target.offsetLeft; target.animate([ { top: oldTop+"px", left: oldLeft+"px" }, { top: newPos[0]+"px", left: newPos[1]+"px" } ], { duration: velocity([oldTop, oldLeft],newPos), fill: 'forwards' }).onfinish = function() { floatHead(); } } var container = document.getElementById("container"), target = document.createElement("img"); target.id = "target"; target.onload = function() { floatHead(); } target.src = "walk.gif"; target.width="200"; container.appendChild(target); </script> </body> </html>复制代码
最后聊聊你关心的各浏览器兼容问题,以下所示显示了各个浏览器的兼容状况:
看来好多都是部分支持,没有彻底支持,笔者也亲自测试了下,在pc端最新版的谷歌浏览器和Firefox是没有任何问题的能够完美运行,笔者的safari仍是运行不起来,在iPhone XS Max没法运行。
做为一名前端开发者,在移动端大行其道怎么能容忍在手机端没有效果,为了在现代浏览器厂商还没彻底跟进到位的时候抢先用上 WAAPI(Web Animation API简称),咱们能够选择引入针对 Web Animation API 的 Polyfill 库 [github.com/web-animati…],从而在 IE/Firefox/Safari 等浏览器上体验到 WAAPI 的精彩。
所以咱们只须要文件里引入如下js,就能够完美体验:
<script src="https://cdn.jsdelivr.net/web-animations/latest/web-animations.min.js"> </script>复制代码
移动端浏览器,Android 5.0 以上的 Android Browser 和 Chrome for Android 自己就已经支持 WAAPI 了,加上 Polyfill 以后,笔者的手机终于能够看到运行效果了,微信里的QQ内核浏览器也能完美运行,pc端的safari也能够完美运行。能够说是全平台支持了,有了这个库你能够放心大胆的使用了。
好了今天的代码撸完了,js代码还不到50行(注:为了在手机端运行,引入了web-animations.min.js),您能够点击"www.qianduandaren.com/demo/walk/"行预览,笔者亲测在iPhone XS Max运行良好,其余手机没有,有待亲们的测试,欢迎到留言区告知。下一篇文章咱们用不到20行的原生js代码纯手工撸一个漂亮的时钟,敬请期待。
更多精彩内容,请微信关注“前端达人”公众号!