【翻译】CSS Animations VS the Web Animations API:案例学习
原文地址:CSS Animations vs the Web Animations API: A Case Study
May 03, 2017 css
, javascript
上周我写了我如何使用CSS来制作bitsofcode logo动画。之后,有人建议我应该对CSS动画与Web Animations API做个对比,所以,这篇文章就是。
Web Animations API介绍
和上周一样,在开始之前我先对Web Animations API做下介绍。Web Animations API向开发者提供了通过JavaScript直接操作浏览器的动画引擎的方法。
创建动画
为了使用Web Animations API创建动画,我们需通过Element.animate()
函数,该函数接受两个参数:keyframes
和options
。
element.animate(keyframes, options);
关键帧 keyframes
关键帧
对象相当于动画中事件的时间轴,这里有两种方式来创建关键帧对象。为了列举这两种方式,这里以grow
动画为例,该动画将会将元素的尺寸放大两倍。如下是通过CSS的@keyframes
来声明:
@keyframes grow {
0% {
transform: none;
}
100% {
transform: scale(2);
}
}
第一种方式
写关键帧
的第一种方式是单个对象形式。对象的每个key代表了我们想要动画的CSS属性。每一个key
的值都是一个由动画过程中的CSS值组成的数组。数组中的每个值表示动画时间轴中的一个点。
const growKeyframes = {
transform: ['none', 'scale(2)']
}
第二种方式
写关键帧
的第二种方式是写一个数组。数组中的每一个项表示动画时间轴中的一个点,在这个点上我们可以定义应用在该点上的每一条CSS属性与值。
const growKeyframes = [
{ transform: 'none' },
{ transform: 'scale(2)' }
]
默认情况下,时间轴上的每个点之间的空间是相等的。例如,如果在时间轴上我有5个点,则每个点之间的动画过渡时间都会是20%。
如果我们想自己改变过渡时间,可以使用上述中的第二种定义方式中的offset
属性。该属性接受一个数字:0-1
之间,表示该点动画应该在什么时候开始,例如,下面的CSS动画:
@keyframes alteredGrow {
0% { transform: none; }
10% { transform: scale(1.5) }
30% { transform: scale(1.9) }
100% { transform: scale(2) }
}
为了说明时间轴上的不相等的空间,我可以通过下面的方式书写:
const alteredGrowKeyframes = [
{ transform: 'none' },
{ transform: 'scale(1.5)', offset: 0.1 }
{ transform: 'scale(1.9)', offset: 0.3 }
{ transform: 'scale(2)' }
]
选项 options
传递给animate()
函数的第二个参数是一个带有动画选项信息的对象。如果我们使用CSS动画,这个对象允许我们指定应用于CSS动画的所有的属性。这里可以定义九个
选项。
选项 | 描述 |
---|---|
id | 动画的唯一索引 |
delay | 定义动画开始前的延迟时间。和CSS属性animation-delay 一致 |
duration | 定义动画一个周期需要的时间。和CSS属性animation-duration 一致 |
iterations | 定义动画重复的次数。和CSS属性animation-iteration-count 一致 |
direction | 定义动画在时间轴的哪个方向运行。和CSS属性animation-direction 一致 |
easing | 定义动画每一步之间如何过渡。和CSS属性animation-timing-function 一致 |
fill | 定义动画在播放前或后,动画效果是否可见。和CSS属性animation-fill-mode 一致 |
endDelay | 当一个动画结束后,到下一个动画开始,中间停留的时间,毫秒 |
iterationStart | 定义动画的循环从哪里开始,可以是0~1,0.5表示动画从中间开始运行 |
举个例子,让我们开始另一个grow动画。利用CSS动画,我们可以让动画持续3秒、无限循环、改变运行方向并且等待2秒后执行,如下是声明代码:
.animated-element {
animation-name: alteredGrow;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-delay: 2s;
}
使用Web Animations API,我们可以通过如下选项来达到相同的效果。
const alteredGrowOptions = {
duration: 3000,
iterations: Infinity,
direction: 'alternate',
delay: 2000
}
使用动画
通过元素的调用的animate()
函数可以将动画应用到该元素上,并且将关键帧(keyframes)
和选项(options)
作为参数。
const element = document.querySelector('.animated-element');
element.animate(alteredGrowKeyframes, alteredGrowOptions);
一旦函数被调用,动画就会自动的开始运行。然而,我们可以通过play()
与pause()
方法来开始与暂停动画。
const element = document.querySelector('.animated-element');
const myAnimation = element.animate(alteredGrowKeyframes, alteredGrowOptions);
myAnimation.pause();
myAnimation.play();
兼容性
动画bitsofcode Logo
和我的CSS动画一样,我从创建好的完整的动画中截取了一小段。下面是三个版本的对比:
创建时间轴
概括来说,如下是logo左侧部分的动画步骤(字母“bitso”中的o是开的,类似(
)。
- 向左移动
- 回到中间
- 停留在中间(等待右边部分向右移动)
- 向左移动
- 旋转
- 慢慢增加旋转
- 回到没有旋转的位置
- 回到中间
基于上述步骤,这是我制作的左边部分的时间轴
下面是基于该时间轴利用Web Animation API创建的关键帧对象,具有时间轴上的每一步的样式规则。
const logoSectionLeftKeyframes = [
{ transform: 'none' },
{ offset: 0.125, transform: 'translateX(-15px)' },
{ offset: 0.25, transform: 'none' },
{ offset: 0.5, transform: 'none' },
{ offset: 0.625, transform: 'translateX(-15px)' },
{ offset: 0.67, transform: 'translateX(-15px) rotate(-10deg)' },
{ offset: 0.72, transform: 'translateX(-15px) rotate(-10deg)' },
{ offset: 0.82, transform: 'translateX(-15px) rotate(-15deg)' },
{ offset: 0.875, transform: 'translateX(-15px)' },
{ transform: 'none' }
];
因为用到了offset
属性,所以这里我决定使用数组形式的keyframes
。
设置参数
每一部分的参数都很简单,每个循环周期时长3秒,并且无限循环。
const logoSectionOptions = {
duration: 3000,
iterations: Infinity
};
应用动画
使用Web Animation API来应用动画要比CSS动画有些繁琐。这是因为我只想当动画被hover
或者focus
的时候来运行。正如我所说的,默认情况下,Web Animation会在创建完之后立即运行。
为了解决这个问题,我不得不创建完动画后立即暂停,然后增加事件监听器
,当事件触发,动画就可以播放或者暂停。另外,因为我要应用动画到每个字符上,那就必须要同时处理几个动画,下面是执行过程:
// 存储所有动画的数组
const animations = [];
function playLogoAnimation() {
animations.map((animation) => animation.play())
}
function pauseLogoAnimation() {
animations.map((animation) => {
animation.pause();
animation.currentTime = 0; // 重置动画为初始状态
})
}
function createLogoAnimation() {
const logoSectionLeftEls = Array.from( document.querySelectorAll('.logo-section-left') );
logoSectionLeftEls.forEach((el) => animations.push(el.animate(logoSectionLeftKeyframes, logoSectionTiming)))
// Animation for middle and right sections here …
// 一旦创建完动画就立即停止
pauseLogoAnimation();
}
createLogoAnimation();
// 时间监听器来开始或暂停动画
const siteTitleLink = document.querySelector('.site__title a');
siteTitleLink.addEventListener('mouseover', playLogoAnimation);
siteTitleLink.addEventListener('mouseout', pauseLogoAnimation);
siteTitleLink.addEventListener('keyup', (e) => {
if ( e.keyCode === 9 ) playLogoAnimation();
});
siteTitleLink.addEventListener('keydown', (e) => {
if ( e.keyCode === 9 ) pauseLogoAnimation();
});
下面是全部动画演示:
CSS Animations VS the Web Animation API
和其他一切一样,无论使用CSS还是JavaScript动画,取决于动画的细节。作为基本规则,CSS动画应该用在小型、和UI相关的动画,比如提示框(tooltip)。Web Animation API应该用作需要微调的更高级的效果。这就是我对这两种动画方式的比价。
性能
CSS vs JavaScript动画的性能会根据我们正在动画的属性而有很大的不同。通常,建议只对transform
或者opacity
属性进行动画,因为这些动画会在与浏览器主线程不同的线程上执行。
改变
transform
并不会触发任何几何形状的改变或渲染,性能会很好。这意味着操作可能在GPU的帮助下由合成器线程执行。
-- CSS Triggers
由于我的动画只用了transform
属性,所以我不能看到这两种方案之间明显的性能差异。通过火狐的开发者工具,我测量了两个动画的帧率,获得了两个相同的帧率:60FPS,即使Main Thread Animation enabled为Off。
我无法找到更多的方式去测量两种方案的性能。如果你知道其他更好的方法,可以在下面留下评论。
开发者经验
在这个例子中,我个人发现CSS动画要比Web Animation API操作简单,更容易使用,主要是因为使用后者来播放暂停动画需要额外的工作。如果我是在做一个更复杂的动画比如一个游戏,Web Animation API会是一个一定要走的路。但是在这个例子中,我认为使用CSS动画更容易实现。
【翻译】CSS Animations VS the Web Animations API:案例学习的更多相关文章
- Web Animations API (JS动画利器)
原文地址:→传送门 写在前面 之前学习了CSS animation/setTimeout/setInterval/requestAnimationFrame等,这些都可以用在某种场景下的小动画,也可以 ...
- Web Animations API & SVG & requestAnimationFrame
Web Animations API WWAPI https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API https:/ ...
- abp学习(四)——根据入门教程(aspnetMVC Web API进一步学习)
Introduction With AspNet MVC Web API EntityFramework and AngularJS 地址:https://aspnetboilerplate.com/ ...
- 关于Web Audio API的入门
Web Audio API提供了一个简单强大的机制来实现控制web应用程序的音频内容.它允许你开发复杂的混音,音效,平移以及更多. 可以先看一下MDN的这篇文章<Web Audio API的运用 ...
- WEB音频API
本文转载至 http://www.webhek.com/web-audio-api 很偶然的,在一个微信公众号里面,看到了这样的一篇文章. WEB音频API.作者分享技术的优良品质值得我们学习. 原文 ...
- H5的Web Audio Api
概述 研究Web Audio Api的主要原因是:工作中需要在ios中实现声音的淡出效果,主要是通过setInterval来改audio标签的volume属性实现的,但是ios上面volume属性是只 ...
- Web Audio API之手把手教你用web api处理声音信号:可视化音乐demo
1.Web Audio API 介绍 Web Audio API 提供了在Web上控制音频的一个非常有效通用的系统 ,这些通用系统通俗的讲就是我们可以利用Web Audio API提供的各种方法操作各 ...
- 使用Web存储API存取本地数据
使用Web存储API TODO:本文由 赤石俊哉 翻译整理,您可以将本文自由地用于学习交流.如需用于其他用途请征得作者的同意. 原文链接:Using the Web Storage API - Moz ...
- HTML5权威指南--Web Storage,本地数据库,本地缓存API,Web Sockets API,Geolocation API(简要学习笔记二)
1.Web Storage HTML5除了Canvas元素之外,还有一个非常重要的功能那就是客户端本地保存数据的Web Storage功能. 以前都是用cookies保存用户名等简单信息. 但是c ...
随机推荐
- 在js中怎样获得checkbox里选中的多个值?
https://zhidao.baidu.com/question/203897221.html 思路:利用name属性值获取checkbox对象,然后循环判断checked属性(true表示被选中, ...
- PHP 获得当前页面所有变量常量的值
get_defined_vars() - 返回由所有已定义变量所组成的数组,这个函数在二次开发的时候用起来非常给力: get_defined_constants();可以返回当前的所有常量 zend的 ...
- Struts2与Ajax数据交互
写在前面: ajax请求在项目中常常使用,今天就平时掌握的总结一下,关于使用ajax请求到Struts2中的action时,前台页面与后台action之间的数据传递交互问题. 这里我主要记录下自己所掌 ...
- OOAD之策略模式(1)
在引入策略模式之前.先用一个小项目解释为什么要有策略模式.这是一个模拟鸭子的小游戏.最开始需求为,所有的鸭子都会叫以及都会游泳且叫声游泳姿势都一样.因此我们用原始OO的思维去编写代码时很容易做到 pu ...
- Hadoop问题:Incorrect configuration: namenode address dfs.namenode.rpc-address is not configured
问题描述:Incorrect configuration: namenode address dfs.namenode.rpc-address is not configured 问题分析:core- ...
- java基础学习总结——java读取properties文件总结
摘录自:http://www.cnblogs.com/xdp-gacl/p/3640211.html 一.java读取properties文件总结 在java项目中,操作properties文件是经常 ...
- Github终于连上了hexo
2018-01-2722:59:28 我的妈呀,看看这感人的网速,哎不想吐槽在中国连外网的速度 总结一下连接过程吧 漫漫长征路,难的要死. 一.github的注册和使用不再详述 二.Git Desk ...
- [Qt Quick] qmlscene工具的使用
qmlscene是Qt 5提供的一个查看qml文件效果的工具.特点是不需要编译应用程序. qmlscene = qml + scene (场景) qmlscene.exe位于Qt的安装目录下 (类似/ ...
- java里程碑之泛型--泛型基本语法
1,java7提供的泛型菱形语法 在java7之前,如果使用带泛型的接口和类定义变量初始化对象的时候,构造器后面也必须带上泛型,这有点恶心的.以前我在公司一直使用的java6,所以我也已经习惯了这种写 ...
- Tomcat系统架构分析
Tomcat系统架构分析 关于这边blog呢,实际开发中并不会用到,但是我觉得还是很有必要认真的写一下.毕竟我们每天在本地撸码的时候使用的就是tomcat来做web服务器.一个常识就是说我们本地在to ...