1. 首页
  2. IT资讯

「Web Animation API 专题」纯手工撸一个图片随机移动的动画

“u003Cdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F27f5d8096a0e48988c101c9fd995cb5a” img_width=”655″ img_height=”396″ alt=”「Web Animation API 专题」纯手工撸一个图片随机移动的动画” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Ch1u003Eu003Cstrongu003EWeb Animation API 介绍u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpu003E当我们谈及网页动画时,自然联想到的是 CSS3 动画、JS 动画、SVG 动画 等技术以及 jQuery.animate() 等动画封装库,根据实际动画内容设计去选择不同的实现方式,然而,每个现行的动画技术都存在一定的缺点,如 CSS3动画必须通过JS去获取动态改变的值,一个动画效果分散在css文件和js文件里不好维护,setInterval 的时间往往是不精确的而且还会卡顿,引入额外的动画封装库也并非对性能敏感的业务适用。u003Cu002Fpu003Eu003Cpu003EWeb Animation API 的历史也应该有几年了,但是每当做动画效果时,笔者就是依赖各种库,很少想着去原生实现,最终造成了我们的项目各种依赖库,体积也不断变大,性能如何也不得而知,作为前端开发的我们多么希望原生的JS去支持通用的动画解决方案, Web Animation API 可能就是一个不错的解决方案。u003Cu002Fpu003Eu003Cpu003EW3C 提出 Web Animation API(简称 WAAPI)正缘于此,它致力于集合 CSS3 动画的性能、JavaScript 的灵活、动画库的丰富等各家所长,将尽可能多的动画控制由原生浏览器实现,并添加许多 CSS 不具备的变量、控制以及或调的选项。它为我们提供了一种通用语言来描述DOM元素的动画,主要方法有:Animation,KeyframeEffect,AnimationEvent,DocumentTimeline,EffectTiming。关于这个API的详细介绍,可以参照MDN的这篇文档,链接地址:https:u002Fu002Fdeveloper.mozilla.orgu002Fen-USu002Fdocsu002FWebu002FAPIu002FWeb_Animations_API。u003Cu002Fpu003Eu003Cpu003E使用Web Animations API,我们可以将交互式动画从样式表移动到JavaScript,将表示与行为分开。我们不再需要依赖DOM的技术,例如编写CSS属性作用于元素以控制方向。为了构建自定义动画库和创建交互式动画,Web Animations API可能是完成工作的完美工具,你无需借助第三方动画库,就可以轻松实现一个效果不错的动画。u003Cu002Fpu003Eu003Cpu003E为了让大家对这个API有个清晰的认识,笔者在接下来的系列文章里,用五六个例子让大家理解这个API,今天笔者将用此API实现一个随机移动的图片开始进行介绍,比如用这个效果我们可以制作一个随机飘浮移动的广告位,游戏里随机走动的怪物等等,本例中的特点就是为了体现Web Animation API的灵活性和强大性,我没有引用任何第三方类库,比如(JQ)以及也没有使用setTimeout和requestAnimationFrame()函数。u003Cu002Fpu003Eu003Cpu003E本篇文章预计时间u003Cstrongu003E 5 u003Cu002Fstrongu003E分钟u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F4310139c4cd84822bffd196fbe850909″ img_width=”938″ img_height=”580″ alt=”「Web Animation API 专题」纯手工撸一个图片随机移动的动画” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Ch1u003Eu003Cstrongu003E动画效果u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpu003E开始前,我们先来看看完成后的动画效果,示例如下效果:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002F991f2af3a4764be38d938204fe5ed768″ img_width=”1930″ img_height=”982″ alt=”「Web Animation API 专题」纯手工撸一个图片随机移动的动画” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Ch1u003Eu003Cstrongu003E页面布局u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpu003E无论图片怎么随机移动,我们都希望在指定的容器里,而不是漫无边际,首先我们在html页面定义容器:u003Cu002Fpu003Eu003Cpreu003E<div id=”container”>u003Cbru003E<u002Fdiv>u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E接下来定义容器的样式:u003Cu002Fpu003Eu003Cpreu003Ebody {u003Cbru003E margin: 0;u003Cbru003E}u003Cbru003Ediv#container {u003Cbru003E height:500px;u003Cbru003E width:100%;u003Cbru003E background: #C6CEF7;u003Cbru003E}u003Cbru003E#target {u003Cbru003E position: absolute;u003Cbru003E filter: drop-shadow(-12px 12px 7px rgba(0,0,0,0.5));u003Cbru003E}u003Cbru003Eu003Cu002Fpreu003Eu003Ch1u003Eu003Cstrongu003E脚本部分u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpu003Eu003Cstrongu003E获取容器u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpreu003Evar container = document.getElementById(“container”);u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cstrongu003E加载动画u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E为了更加直观性,我选择一个走动的gif图片,由于图片的加载需要一些时间,为了不破坏动画的连贯性,确保图片加载完了我们在执行动画,相关代码如下:u003Cu002Fpu003Eu003Cpreu003Evar target = document.createElement(“img”);u003Cbru003Etarget.id = “target”;u003Cbru003Etarget.onload = function() {u003Cbru003E floatHead();u003Cbru003E}u003Cbru003Etarget.src = “walk.gif”;u003Cbru003Econtainer.appendChild(target);u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E大家都看到了,onload部分我们加载了floatHead()函数,接下来我们来进行相关实现,此函数主要包含以下功能:创建一个随机位置,计算移动时间,封装移动动画。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E随机位置u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E我们利用Math.floor函数实现了其随机位置的变化,示例代码如下:u003Cu002Fpu003Eu003Cpreu003Efunction makeNewPosition() {u003Cbru003E var containerVspace = container.offsetHeight – target.offsetHeight,u003Cbru003E containerHspace = container.offsetWidth – target.offsetWidth,u003Cbru003E newX = Math.floor(Math.random() * containerVspace),u003Cbru003E newY = Math.floor(Math.random() * containerHspace);u003Cbru003E return [newX, newY];u003Cbru003E}u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E这里的随机位置,我们返回了一个数组,描述的是图片相对容器的位置,即top,left。这里你需要理解offsetHeight,offsetWidth,可理解为div的可视高度或宽度,样式的height或Width+上下padding或左右padding+上下border-width或左右border-width。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E计算时间u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E动画是有时间属性的,我们进行位置的移动,需要花多久时间,假设运动速度为0.1个单位u002F毫秒。这个函数包含两个数组:prev为当前目标的原始X和Y位置,next为移动目标的位置。此函数没有进行进行精确的距离计算,只是判断了x和y轴上移动的距离大小用最大的距离除以速度,示例代码如下:u003Cu002Fpu003Eu003Cpreu003Efunction velocity(prev, next) { u003Cbru003E var x = Math.abs(prev[1] – next[1]),u003Cbru003E y = Math.abs(prev[0] – next[0]),u003Cbru003E larger = x > y ? x : y,u003Cbru003E speedModifier = 0.1,u003Cbru003E time = Math.ceil(larger u002F speedModifier);u003Cbru003E return time; u003Cbru003E}u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003Eu003Cstrongu003E封装移动动画u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E接下来是我们Web Animations API的核心部分,我们使用其核心API在加上上述我们完成的两个函数让其动起来,示例代码如下:u003Cu002Fpu003Eu003Cpreu003Efunction floatHead() {u003Cbru003E var newPos = makeNewPosition(),u003Cbru003E oldTop = target.offsetTop,u003Cbru003E oldLeft = target.offsetLeft,u003Cbru003E target.animate([u003Cbru003E { top: oldTop+”px”, left: oldLeft+”px” },u003Cbru003E { top: newPos[0]+”px”, left: newPos[1]+”px” }u003Cbru003E ], {u003Cbru003E duration: velocity([oldTop, oldLeft],newPos),u003Cbru003E fill: “forwards”u003Cbru003E }).onfinish = function() {u003Cbru003E floatHead();u003Cbru003E }u003Cbru003E}u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E该Animation的animate函数有两个参数,一个是KeyframeEffects数组和AnimationEffectTimingPropertiesoptions 的对象。基本上,第一个参数映射到您将放入CSS中的内容@keyframes,你可以想象成css中的@keyframes内容,比如以下代码:u003Cu002Fpu003Eu003Cpreu003E@keyframes emphasis {u003Cbru003E 0% {u003Cbru003E transform: scale(1); u003Cbru003E opacity: 1; u003Cbru003E }u003Cbru003E 30% {u003Cbru003E transform: scale(.5); u003Cbru003E opacity: .5; u003Cbru003E }u003Cbru003E 78.75% {u003Cbru003E transform: scale(.667); u003Cbru003E opacity: .667; u003Cbru003E }u003Cbru003E 100% {u003Cbru003E transform: scale(.6);u003Cbru003E opacity: .6; u003Cbru003E }u003Cbru003E}u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E你可以将“{}”里的信息顺序依次放到一个数组里;第二个参数是时间控制 timing,包括有 duration 持续时间、iterations 执行次数、direction 动画方向、easing 缓动函数等属性。比如以下代码:u003Cu002Fpu003Eu003Cpreu003E#toAnimate {u003Cbru003E animation: emphasis 700ms ease-in-out 10ms infinite alternate forwards;u003Cbru003E}u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E你还可能注意到我们使用了onfinish事件完成了floatHead函数的反复调用,其是Animation的属性,监听动画完成事件,如果动画完成继续执行floatHead(),相当不断的递归调用。u003Cu002Fpu003Eu003Ch1u003Eu003Cstrongu003E最终完成的代码u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpreu003E<!DOCTYPE html>u003Cbru003E<html lang=”en”>u003Cbru003E<head>u003Cbru003E <style>u003Cbru003E body {u003Cbru003E margin: 0;u003Cbru003E }u003Cbru003E div#container {u003Cbru003E height:500px;u003Cbru003E width:100%;u003Cbru003E background: #C6CEF7;u003Cbru003E }u003Cbru003E #target {u003Cbru003E position: absolute;u003Cbru003E filter: drop-shadow(-12px 12px 7px rgba(0,0,0,0.5));u003Cbru003E }u003Cbru003E <u002Fstyle>u003Cbru003E <meta charset=”UTF-8″>u003Cbru003E <title>前端达人示例展示——图片随机移动<u002Ftitle>u003Cbru003E<u002Fhead>u003Cbru003E<body>u003Cbru003E<div id=”container”><u002Fdiv>u003Cbru003E<script>u003Cbru003E function makeNewPosition() {u003Cbru003E var containerVspace = container.offsetHeight – target.offsetHeight,u003Cbru003E containerHspace = container.offsetWidth – target.offsetWidth,u003Cbru003E newX = Math.floor(Math.random() * containerVspace),u003Cbru003E newY = Math.floor(Math.random() * containerHspace);u003Cbru003E return [newX, newY];u003Cbru003E }u003Cbru003E function velocity(prev, next) {u003Cbru003E var x = Math.abs(prev[1] – next[1]),u003Cbru003E y = Math.abs(prev[0] – next[0]),u003Cbru003E larger = x > y ? x : y,u003Cbru003E speedModifier = 0.2,u003Cbru003E time = Math.ceil(larger u002F speedModifier);u003Cbru003E return time;u003Cbru003E }u003Cbru003E function floatHead() {u003Cbru003E var newPos = makeNewPosition(),u003Cbru003E oldTop = target.offsetTop,u003Cbru003E oldLeft = target.offsetLeft;u003Cbru003E target.animate([u003Cbru003E { top: oldTop+”px”, left: oldLeft+”px” },u003Cbru003E { top: newPos[0]+”px”, left: newPos[1]+”px” }u003Cbru003E ], {u003Cbru003E duration: velocity([oldTop, oldLeft],newPos),u003Cbru003E fill: ‘forwards’u003Cbru003E }).onfinish = function() {u003Cbru003E floatHead();u003Cbru003E }u003Cbru003E }u003Cbru003E var container = document.getElementById(“container”),u003Cbru003E target = document.createElement(“img”);u003Cbru003E target.id = “target”;u003Cbru003E target.onload = function() {u003Cbru003E floatHead();u003Cbru003E }u003Cbru003E target.src = “walk.gif”;u003Cbru003E target.width=”200″;u003Cbru003E container.appendChild(target);u003Cbru003E<u002Fscript>u003Cbru003E<u002Fbody>u003Cbru003E<u002Fhtml>u003Cbru003Eu003Cu002Fpreu003Eu003Ch1u003E兼容情况u003Cu002Fh1u003Eu003Cpu003E最后聊聊你关心的各浏览器兼容问题,如下所示显示了各个浏览器的兼容情况:u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002F028b2625ebe64a8f89601b03312f5432″ img_width=”1448″ img_height=”542″ alt=”「Web Animation API 专题」纯手工撸一个图片随机移动的动画” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fpgc-imageu002Fee6adc65fff349579a4f5f6ad5e2f8d7″ img_width=”972″ img_height=”558″ alt=”「Web Animation API 专题」纯手工撸一个图片随机移动的动画” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E看来好多都是部分支持,没有完全支持,笔者也亲自测试了下,在pc端最新版的谷歌浏览器和Firefox是没有任何问题的可以完美运行,笔者的safari还是运行不起来,在iPhone XS Max无法运行。u003Cu002Fpu003Eu003Cpu003E作为一名前端开发者,在移动端大行其道怎么能容忍在手机端没有效果,为了在现代浏览器厂商还没完全跟进到位的时候抢先用上 WAAPI(Web Animation API简称),我们可以选择引入针对 Web Animation API 的 Polyfill 库 [https:u002Fu002Fgithub.comu002Fweb-animationsu002Fweb-animations-js],从而在 IEu002FFirefoxu002FSafari 等浏览器上体验到 WAAPI 的精彩。u003Cu002Fpu003Eu003Cpu003E因此我们只需要文件里引入以下js,就可以完美体验:u003Cu002Fpu003Eu003Cpreu003E<script src=”https:u002Fu002Fcdn.jsdelivr.netu002Fweb-animationsu002Flatestu002Fweb-animations.min.js”><u002Fscript>u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E移动端浏览器,Android 5.0 以上的 Android Browser 和 Chrome for Android 本身就已经支持 WAAPI 了,加上 Polyfill 之后,笔者的手机终于可以看到运行效果了,微信里的QQ内核浏览器也能完美运行,pc端的safari也可以完美运行。可以说是全平台支持了,有了这个库你可以放心大胆的使用了。u003Cu002Fpu003Eu003Ch1u003Eu003Cstrongu003E小节u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpu003E好了今天的代码撸完了,js代码还不到50行(注:为了在手机端运行,引入了web-animations.min.js),您可以点击”https:u002Fu002Fwww.qianduandaren.comu002Fdemou002Fwalku002F”行预览,笔者亲测在iPhone XS Max运行良好,其他手机没有,有待亲们的测试,欢迎到留言区告知。下一篇文章我们用不到20行的原生js代码纯手工撸一个漂亮的时钟,敬请期待。u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002Fdbcf16f90e334b5e9738082faefb584b” img_width=”900″ img_height=”600″ alt=”「Web Animation API 专题」纯手工撸一个图片随机移动的动画” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E更多精彩内容,请微信关注u003Cstrongu003E“前端达人”公众号u003Cu002Fstrongu003E!u003Cu002Fpu003Eu003Cu002Fdivu003E”

原文始发于:「Web Animation API 专题」纯手工撸一个图片随机移动的动画

主题测试文章,只做测试使用。发布者:杀手梦三刀,转转请注明出处:http://www.cxybcw.com/10740.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code