Web Animation API 用js编写更加自由的web动画

在网页中使用动画可以提供更好的用户体验,目前为止,web 动画可以通过 css3 transitions,css3 keyframes 或者其他的动画库(animate.css、Velocity、tween),现在我们可以使用 js 编写更加自由的 web 动画,那就是 web animation。但是每当做动画效果时,很多小伙伴们(包括我)就是依赖各种库,很少想着去原生实现,最终造成了我们的项目各种依赖库,体积也不断变大,性能如何也不得而知,作为前端开发的我们多么希望原生的 JS 去支持通用的动画解决方案, Web Animation API 可能就是一个不错的解决方案。
W3C 提出 Web Animation API(简称 WAAPI)正缘于此,它致力于集合 CSS3 动画的性能、JavaScript 的灵活、动画库的丰富等各家所长,将尽可能多的动画控制由原生浏览器实现,并添加许多 CSS 不具备的变量、控制以及或调的选项。它为我们提供了一种通用语言来描述 DOM 元素的动画,主要方法有:Animation,KeyframeEffect,AnimationEvent,DocumentTimeline,EffectTiming。关于这个 API 的详细介绍,可以参照 MDN 的这篇文档,链接地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Animations_API
使用 Web Animations API,我们可以将交互式动画从样式表移动到 JavaScript,将表示与行为分开。我们不再需要依赖 DOM 的技术,例如编写 CSS 属性作用于元素以控制方向。为了构建自定义动画库和创建交互式动画,Web Animations API 可能是完成工作的完美工具,你无需借助第三方动画库,就可以轻松实现一个效果不错的动画。
入门:从实例开始
WAAPI 核心在于提供了
Element.animate()
最简单的例子:
document.body.animate( [{'background': 'red'}, {'background': 'green'}, {'background': 'blue'}] , 3000);
使用 Chrome 39 以上的浏览器运行一下,页面背景色进行了红绿蓝的依次过渡,3s 后结束。我们当然是不会满足于这么简单的控制参数,继续看下个例子:
var dot = document.querySelector('.dot');
var frames = [
{transform: 'rotate(0deg) translate(80px)'},
{transform: 'rotate(360deg) translate(80px) '},
];
var timing = {
duration: 2500, //ms
delay: 0, //ms
iterations: Infinity, //1, 2, 3 ...
Infinity direction: 'alternate', //'normal', 'reverse'等
easing: 'ease-in-out', //'linear', 'ease-in'等
fill: 'forwards', //'backwards', 'both', 'none', 'auto'
};
dot.animate(frames, timing);
可以看到 DOM 节点具备全新的 animate 方法,第一个参数是关键帧数组 frames[],对应 CSS3 中的@keyframes,每一帧的描述与 CSS3 极其类似;第二个参数是时间控制 timing,包括有 duration 持续时间、iterations 执行次数、direction 动画方向、easing 缓动函数等属性。是不是很像 CSS3 的语法,以上 timing 参数等同于:
.dot { animation: frames 2500ms ease-in-out 0ms infinite alternate forwards; }
效果如下所示:

上面只是一个小小的入门,接下来看看大家都关心的兼容性问题
浏览器兼容
如下所示显示了各个浏览器的兼容情况:


由上图看出,好多都是部分支持,没有完全支持,笔者也亲自测试了下,在 pc 端最新版的谷歌浏览器和 Firefox 是没有任何问题的可以完美运行,笔者的 safari 还是运行不起来,在 iPhone XS Max 无法运行。
作为一名前端开发人员,在移动端大行其道怎么能容忍在手机端没有效果,为了在现代浏览器厂商还没完全跟进到位的时候抢先用上 WAAPI(Web Animation API 简称),我们可以选择引入针对 Web Animation API 的 Polyfill 库 [https://github.com/web-animations/web-animations-js],从而在 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 也可以完美运行。可以说是全平台支持了,有了这个库你可以放心大胆的使用了。
实例展示
开始前,我们先来看看完成后的动画效果,示例如下效果:

无论图片怎么随机移动,我们都希望在指定的容器里,而不是漫无边际。
HTML 代码:
<div id="container"></div>
CSS 代码:
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>
声明:文章转自公众号:前端达人,只为学习交流,如有侵权请联系博主删除,谢谢
以上关于Web Animation API 用js编写更加自由的web动画的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » Web Animation API 用js编写更加自由的web动画

微信
支付宝