CSS3动画 相比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 + ; /* UPDATE */ currentLeft = element.style.left; /* QUERY */
element.style.left = currentLeft + ; /* UPDATE */ /* 没有布局震荡 */
currentTop = element.style.top; /* QUERY */
currentLeft = element.style.left; /* QUERY */ element.style.top = currentTop + ; /* UPDATE */
element.style.left = currentLeft + ; /* UPDATE */
发生在更新之后的查询会强制浏览器立马重新布局,并计算给出页面样式的计算值(把更新的影响考虑在内)。这对于运行于16ms间隔的动画来讲,会产生巨大的开销。
同样,实现RAF并不需要对既有代码改动很大。让我们来对比一下RAF的实现和setInterval的实现:
var startingTop = ; /* setInterval: 每16ms运行一次来达到60fps (1000ms/60 ~= 16ms). */
setInterval(function() {
/* 由于这里的代码会在1s内执行60次,所以我们把top属性每秒1单位的增长分成60份 */
element.style.top = (startingTop += /);
}, ); /* requestAnimationFrame: 不管浏览器是否处于最优状态,都试图运行在60fps */
function tick () {
element.style.top = (startingTop += /);
} 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: , top: "50%" })
/* 延迟1000ms,元素滑动出视图 */
.velocity({ opacity: , top: "-50%" }, { delay: });
在上面的例子中,第二个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()
/* 使用Velocity的2000ms内改变元素top属性的动画*/
.velocity({ top: "50%" }, )
/* 当上面Velocity动画执行完时,使用标准的jQuery方法来使元素淡出*/
.fadeOut();
办公资源网址导航 https://www.wode007.com
在高级动画上,复杂的滚动场景和三维动画都可以创建——只需要两行简单的代码:
$element
/* 在1000ms内,浏览器滚动到这个元素的顶部 */
.velocity("scroll", )
/* 之后使元素绕着它的Y轴旋转360度。 */
.velocity({ rotateY: "360deg" }, );
结束语
Velocity的目标是保持领先的DOM动画性能和便捷。本文的重点是前者。请去VelocityJS.org学习更多关于后者的知识。
在我们结束之前,记得*一个高性能的UI不仅仅是选择合适的动画库。页面的其余部分也应该优化。从下面这些奇妙的Google话题中学习更多:
CSS3动画 相比JS Animation 哪个更快?的更多相关文章
- CSS vs. JS Animation: 哪个更快
CSS vs. JS Animation: 哪个更快? CSS vs. JS Animation: 哪个更快? 基于JavaScript的动画竟然已经默默地比CSS的transition动画快了?而且 ...
- css3 动画 vs js 动画
之前被问到过,css3 动画与 js 动画孰优孰劣,脑袋的第一反应就是性能上肯定 css3 动画会好很多,但别人说不对,我就在想,不对?难道还有别的原因吗?答案是肯定的.先来看看二者实现动画的原理吧. ...
- CSS3动画和JS动画的比较
前言 之前有被问到一个问题,css3动画和js动画性能谁更好,为什么.据我的经验,当然觉得css3动画性能更好,至于为什么一时还真答不上来,所以特意查了一下资料总结一波. JS动画 优点: js动画控 ...
- 使用jquery封装的动画脚本(无动画、css3动画、js动画)
自己封装好的showhide.js 包含无动画.css3动画.js动画 包括:fade(淡入淡出) slideUpDown(上下滑动) slideLeftRight(左右滑动) fadeSlid ...
- css3动画与js动画的一些理解
http://zencode.in/19.CSS-vs-JS%E5%8A%A8%E7%94%BB%EF%BC%9A%E8%B0%81%E6%9B%B4%E5%BF%AB%EF%BC%9F.html 首 ...
- CSS3动画效果——js调用css动画属性并回调处理详解
http://www.jb51.net/css/258407.html 这篇文章主要详细介绍了CSS3动画效果回调处理,需要的朋友可以参考下 我们在做js动画的时候,很多时候都需要做回调处理,如在一个 ...
- CSS3动画与JS动画的优缺点?
JS动画: 缺点:1.JS在浏览器的主线程中运行,而主线程还有其他的js脚本,样式布局,绘制任务等,对其干扰可能导致线程出现阻塞,从而造成丢帧的情况. 2.JS动画代码复杂度高于CSS3动画. 优点: ...
- css3动画与js动画的区别
css与 js动画 优缺点比较 我们经常面临一个抉择:到底使用JavaScript还是CSS动画,下面做一下对比 JS动画 缺点:(1)JavaScript在浏览器的主线程中运行,而主线程中还有其 ...
- css3动画和JS+DOM动画和JS+canvas动画比较
css3兼容:IE10+.FF.oprea(animation):safari.chrome(-webkit-animation) js+dom:没有兼容问题: js+canvas:IE9+:(性能最 ...
随机推荐
- Java实现 黑洞数
任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到一个最大的数:65432,一个最小的数23456.求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则 ...
- 分享一个新出炉的JVM里不痛不痒的BUG(Attach机制相关)
本文来自: PerfMa技术社区 PerfMa(笨马网络)官网 概述 老早之前写过一篇文章,关于attach机制的,可以看下这篇老文章了解一下JVM源码分析之Attach机制实现完全解读,比如大家常用 ...
- 关于C#委托三种调用的分享
一.同步调用 1.同步调用会按照代码顺序来执行2.同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕的用户体验,这时候异步调用就很有必要了. 举个栗子 ...
- vue的第一个commit分析
为什么写这篇vue的分析文章? 对于天资愚钝的前端(我)来说,阅读源码是件不容易的事情,毕竟有时候看源码分析的文章都看不懂.每次看到大佬们用了1-2年的vue就能掌握原理,甚至精通源码,再看看自己用了 ...
- Spring系列.依赖注入配置
依赖注入的配置 Spring的依赖注入分为基于构造函数的依赖注入和基于setter方法的依赖注入. 基于构造函数的依赖注入 <!-- 通过构造器参数索引方式依赖注入 --> <bea ...
- WinForm通用自动更新AutoUpdater项目实战
目前我们做的上位机项目还是以Winform为主,在实际应用过程中,可能还会出现一些细节的修改.对于这种情况,如果上位机带有自动更新功能,我们只需要将更新后的应用程序打包放在指定的路径下,可以让用户自己 ...
- css布局中的垂直水平居中对齐
前言 我们都知道,固定高宽的div在网页中垂直居中很简单,相信大家也很容易的写出来,但是不是固定高宽的div如何垂直居中呢?我们在网页布局,特别是手机等web端网页经常是不固定高宽的div,那么这些d ...
- 完美解决PYQT5登录界面跳转主界面方法
该问题,有很多种方法,但是很多方法要么这个有问题,要么那个有问题,最后终于找到一种没问题的方法.记录一下: Login.py(登录窗口)文件 import sys from PyQt5 import ...
- SpringMVC的url-pattern配置及原理剖析
SpringMVC的url-pattern配置及原理剖析 xml里面配置标签: <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc./ ...
- CAS(乐观锁)与ABA问题
cas是什么 CAS 全称 compare and swap 或者compare and exchange 比较并且交换.用于在没有锁的情况下,多个线程对同一个值的更新. cas原理 例如,我们对一 ...