CSS vs. JS Animation: 哪个更快
CSS vs. JS Animation: 哪个更快?
基于JavaScript的动画竟然已经默默地比CSS的transition动画快了?而且,Adobe和 Google竟然一直在发布可以媲美原生应用的富媒体移动站点?
这篇文章将会逐点讲解基于JavaScript的DOM动画库,比如Velocity.js和GSAP,是如何比jQuery和基于CSS的动画库高效的。
jQuery
让我们先从这个事实开始:JavaScript和jQuery被错误的混淆了。JavaScript的动画是快的,但是jQuery的动画慢。为什么?因为虽然jQuery很强大,但是它的目标从来不是为了成为一个高效的动画引擎。
jQuery不能避免布局震荡因为它的代码除了动画还提供了很多功能。
jQuery的内存消耗经常触发垃圾回收,导致动画卡住
jQuery使用setInterval而不是requestAnimationFrame (RAF)为了避免一些bug
注意,布局震荡引起了动画开始处的卡顿,垃圾回收导致了动画进行中的卡顿,RAF的缺席导致了帧率低。
实现的例子
避免布局震荡,包括简单地合并DOM查询和DOM更新:
var currentTop,
currentLeft;
/* 有布局震荡 */
currentTop = element.style.top; /* QUERY */
element.style.top = currentTop + 1; /* UPDATE */
currentLeft = element.style.left; /* QUERY */
element.style.left = currentLeft + 1; /* UPDATE */
/* 没有布局震荡 */
currentTop = element.style.top; /* QUERY */
currentLeft = element.style.left; /* QUERY */
element.style.top = currentTop + 1; /* UPDATE */
element.style.left = currentLeft + 1; /* UPDATE */
发生在更新之后的查询会强制浏览器立马重新布局,并计算给出页面样式的计算值(把更新的影响考虑在内)。这对于运行于16ms间隔的动画来讲,会产生巨大的开销。
同样,实现RAF并不需要对既有代码改动很大。让我们来对比一下RAF的实现和setInterval的实现:
var startingTop = 0;
/* setInterval: 每16ms运行一次来达到60fps (1000ms/60 ~= 16ms). */
setInterval(function() {
/* 由于这里的代码会在1s内执行60次,所以我们把top属性每秒1单位的增长分成60份 */
element.style.top = (startingTop += 1/60);
}, 16);
/* requestAnimationFrame: 不管浏览器是否处于最优状态,都试图运行在60fps */
function tick () {
element.style.top = (startingTop += 1/60);
}
window.requestAnimationFrame(tick);
RAF极大限度地提高了动画的性能。而您只需要修改为数不多的代码。
CSS Transitions
CSS transitions的动画性能优于jQuery,它把动画的逻辑交给了浏览器本身。这会有助于:1)优化DOM交互和内存消耗以避免卡顿,2)在底层借助RAF的特性,3)强制硬件加速(借助GPU的能力来提高动画性能)。
然而,实际情况是,这些优化可以直接通过JavaScript来实现,GSAP已经致力于此多年。Velocity.js,一个新的动画引擎,不止借助于上述技术,还应用了其他方法--我们将很快探讨。
明白JavaScript动画可以媲美CSS动画库这一事实,只是我们计划的第一步。第二步是我们要明白JavaScript动画可以比CSS动画还快。
让我们从检查CSS动画库的缺陷开始:
Transitions的强制硬件加速是使GPU加速,然而这反而会导致GPU强压状况下动画的卡顿。这些影响在移动设备上更为严重。(特别地,这个卡顿是由于数据在浏览器的主线程和排序线程间传递的开销导致的。一些CSS属性,比如transforms和opacity,是不受这个开销影响的。)Adobe在这里阐述了这个问题。
Transitions在IE10以下有兼容问题, 这在PC端站点会很容易导致问题发生,因为IE8和IE9依然很流行。
因为transitions并不是被JavaScript控制(它们只是被JavaScript触发),浏览器并不知道如何同步地使用JavaScript代码来操控优化transitions。
相反地:基于JavaScript的动画库,可以自己决定什么时候使用硬件加速,可以兼容所有版本的IE,并且它们非常适合批量动画优化。
我的建议是,当您只是开发移动站点,并且您的动画只包含简单的状态变化时,可以使用原生CSS transitions。在这种情况下,transitions算是一种高效并且原生的解决方案,并且可以把所有的动画逻辑只放在css中,避免了因为引入JavaScript库而导致页面臃肿。但是,如果您正在设计复杂的UI,或者正在开发具有状态UI的应用程序,请使用JavaScript动画库,它可以使您的动画保持高性能,使您的工作流程保持可控。特别是在管理CSStransitions方面做得很棒的一个库是 Transit。
JavaScript Animation
Okay,所以JavaScript在性能上可以占上风。但是JavaScript究竟可以快多少呢?其实,它已经快到可以创建复杂的,通常只能用WebGL构建的3D animation demo。已经快到可以创建通常只能用Flash或者影效处理做到的multimedia teaser。已经快到可以创建通常只能用canvas构建的virtual world。
为了直观比较动画库的领先性能,包括Transit(内部使用CSS transitions),请查阅Velocity的文档,在VelocityJS.org。
依然存在问题:JavaScript究竟如何达到高性能?下面是基于JavaScript的动画库能实现的优化列表:
为了减小布局震荡,将整个动画中涉及到DOM同步化到堆栈中。
缓存链式调用中的属性值,以尽量减少DOM查询(它是影响DOM动画性能的致命弱点)的发生。
在同一个跨同级元素调用中缓存单位转换比率(例如PX到%、em等)。
当样式更新在视觉上不明显时,跳过更新。
回顾之前讲的布局震荡,Velocity.js利用这些最佳实践来缓存动画的结束值,这些值会被重用为之后动画的开始值,从而避免再次查询DOM元素的初始值:
$element
/* 将元素向下滑动到视图中。 */
.velocity({ opacity: 1, top: "50%" })
/* 延迟1000ms,元素滑动出视图 */
.velocity({ opacity: 0, top: "-50%" }, { delay: 1000 });
在上面的例子中,第二个Velocity自动知道它应该从opacity为1,top为50%开始。
浏览器最终可以自己执行很多相同的优化,但这样做将需要极大地限制开发人员编写动画代码的方式。因此,同样的原因,jQuery不使用RAF(见上文),浏览器也永远不会强加优化,即使这些优化只有非常小的可能会打破规范或偏离预期的行为。
最后,让我们来比较一下这两个JavaScript动画库(Velocity.js和GSAP)。
GSAP是一种快速、功能丰富的动画平台。Velocit是一个轻量级工具,可以极大地提高UI动画性能和工作流程。
GSAP需要许可费。Velocity是通过许MIT开源的。
性能都很优异,GSAP和Velocity在真实项目中没有区别。
我的建议是:当您需要精确的控制(例如重映,暂停/恢复/搜索)、运动(例如Bezier曲线路径),或复杂的分组/排序时,使用GSAP。这些特性对于游戏开发和某些niche应用非常重要,但在Web应用程序的UI中并不常见。
Velocity.js
定位GSAP功能丰富,并不意味着Velocity功能单一。相反地,在压缩后只有7Kb的文件中,Velocity不仅提供了jQuery$.animate()的所有功能,而且提供了color animation,transforms,loops,easings,class animation和scrolling。
简而言之,Velocity是jQuery、jQuery UI和CSStransitions的最佳组合。
进一步,从方便的角度,Velocity在底层使用jQuery的$.queue()方法,因此可以无缝地与jQuery的$.animate(), $.fade()和$.delay()函数交互。并且,由于Velocity的语法和$.animate()一致,您页面的代码不需要修改。
让我们快速看一下Velocity.js。在基础动画上,Velocity和$.animate()一样:
$element
.delay(1000)
/* 使用Velocity的2000ms内改变元素top属性的动画*/
.velocity({ top: "50%" }, 2000)
/* 当上面Velocity动画执行完时,使用标准的jQuery方法来使元素淡出*/
.fadeOut(1000);
在高级动画上,复杂的滚动场景和三维动画都可以创建——只需要两行简单的代码:
$element
/* 在1000ms内,浏览器滚动到这个元素的顶部 */
.velocity("scroll", 1000)
/* 之后使元素绕着它的Y轴旋转360度。 */
.velocity({ rotateY: "360deg" }, 1000);
结束语
Velocity的目标是保持领先的DOM动画性能和便捷。本文的重点是前者。请去VelocityJS.org学习更多关于后者的知识。
在我们结束之前,记得_*一个高性能的UI不仅仅是选择合适的动画库_。页面的其余部分也应该优化。从下面这些奇妙的Google话题中学习更多:
本文转载自:众成翻译
译者:凯小凯
审校: betsey
链接:http://www.zcfy.cc/article/4635
原文:https://davidwalsh.name/css-js-animation
CSS vs. JS Animation: 哪个更快的更多相关文章
- CSS3动画 相比JS Animation 哪个更快?
CSS vs. JS Animation: 哪个更快? 基于JavaScript的动画竟然已经默默地比CSS的transition动画快了?而且,Adobe和 Google竟然一直在发布可以媲美原生应 ...
- CSS 和 JS 动画哪个更快
基于Javascript的动画暗中同CSS过渡效果一样,甚至更加快,这怎么可能呢?而Adobe和Google持续发布的富媒体移动网站的性能可媲美本地应用,这又怎么可能呢? 本文逐一遍览了基于Javas ...
- JQuery动画插件Velocity.js发布:更快的动画切换速度
5月3日,Julian在其GitHub上发布了Velocity.js.Velocity.js是一款动画切换的jQuery插件,它重新实现了jQuery的$.animate()方法从而加快动画切换的速度 ...
- Velocity.js发布:更快的动画切换速度
Velocity.js是一款动画切换的jQuery插件,它重新实现了jQuery的$.animate()方法从而加快动画切换的速度.Velocity.js只有7k的大小,它不仅包含了$.animate ...
- 自从用了Less 编写css,你比以前更快了~
之所以用这个标题呢,主要是最近调侃杰伦太有意思了. 好吧,开个玩笑而已. 如果你了解过Less,并对之很熟悉,就不用往下看了. 如果你没用过,恭喜,这是一个入门级的教程,学会了它,可以为你节省10%的 ...
- 自从用了Less 编写css,你比以前更快了~(sublime编译)
之所以用这个标题呢,主要是最近调侃杰伦太有意思了. 好吧,开个玩笑而已. 如果你了解过Less,并对之很熟悉,就不用往下看了. 如果你没用过,恭喜,这是一个入门级的教程,学会了它,可以为你节省10%的 ...
- CSS VS JS动画,哪个更快[译]
英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js ...
- 让你的 Node.js 应用跑得更快的 10 个技巧(转)
Node.js 受益于它的事件驱动和异步的特征,已经很快了.但是,在现代网络中只是快是不行的.如果你打算用 Node.js 开发你的下一个Web 应用的话,那么你就应该无所不用其极,让你的应用更快,异 ...
- 更轻更快的Vue.js 2.0与其他框架对比(转)
更轻更快的Vue.js 2.0 崭露头角的JavaScript框架Vue.js 2.0版本已经发布,在狂热的JavaScript世界里带来了让人耳目一新的变化. Vue创建者尤雨溪称,Vue 2.0 ...
随机推荐
- 微服务常见安全认证方案Session token cookie跨域
HTTP 基本认证 HTTP Basic Authentication(HTTP 基本认证)是 HTTP 1.0 提出的一种认证机制,这个想必大家都很熟悉了,我不再赘述.HTTP 基本认证的过程如下: ...
- spring学习地址
http://developer.51cto.com/art/201006/205212_2.htm
- android全屏下的输入框未跟随软键盘弹起问题
最近开发中遇到,全屏模式下输入框在底部不会跟随软键盘弹起.于是网上搜索了解决的方案.大致找到了两种方案. 第一种 定义好此类 public class SoftKeyBoardListener { p ...
- PHP第四天 函数引用传值
<?php function f1($p1,&$p2){ $p1++; $p2++; $result= $p1+ $p2; return $result;}$v1=10;$v2=20;$ ...
- Oracle经验积累
Oracle 常用Funtion ----行转列 开始---- select u_id, wmsys.wm_concat(goods) goods_sum from shopping group by ...
- 【转载】java实现HTTP请求的三种方式
目前JAVA实现HTTP请求的方法用的最多的有两种:一种是通过HTTPClient这种第三方的开源框架去实现.HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,Ht ...
- 04-Linux系统编程-第01天(文件IO、阻塞非阻塞)
03-系统函数 系统编程章节大纲 1 文件I/O 2 文件系统 3 进程 4 进程间通信 5 信号 6 进程间关系 7 守护进程 8 线程 9 线程同步 10 网络基础 11 socket编程 12 ...
- swift-UITableView的基本使用
废话不多说了,直接贴我今天写的代码吧:如果新手有什么不懂的,可以发我邮箱. // // singleInfo.swift 个人信息 // Housekeeper // // ...
- POJ2431-Expedition【优先队列+贪心】
题目大意:卡车每走一公里就消耗一单位的汽油,初始时给你p单位油,你要到达l距离的终点.其中路上有n个补给点可以加油,并且油箱容量无限大,问你最少可以停车几次. 思路:因为油箱无限大,所以我们可以这么认 ...
- luogu 2483 K短路 (可持久化左偏树)
题面: 题目大意:给你一张有向图,求1到n的第k短路 $K$短路模板题 假设整个图的边集为$G$ 首先建出以点$n$为根的,沿反向边跑的最短路树,设这些边构成了边集$T$ 那么每个点沿着树边走到点$n ...