CSS vs JS动画:谁更快?

CSS vs JS动画:谁更快?

2016-05-16 前端大全

(点击上方公众号,可快速关注)

英文:Julian Shapiro

译者:MZhou‘s blog

链接:http://zencode.in/19.CSS-vs-JS动画:谁更快?.html

这篇文章翻译自 Julian Shapiro 的 CSS vs. JS Animation: Which is Faster?。Julian Shapiro 也是 Velocity.js 的创造者。这是一个非常高效、简单易用的JS动画库。他在Web动画方面有很高的造诣。

Javascript 动画怎么可能总是和 CSS transition 一样快,甚至更快呢?到底是什么秘密呢?Adobe 和 Google 是怎么做到让他们的富媒体移动网站的速度和 native app 媲美的?

这篇文章会一步步告诉你为什么基于 Javascript 的 DOM 动画库(比如 Velocity.js 和 GSAP)能够比 jQuery 和基于 CSS 的动画库更高效。

jQuery

让我们从基本开始说起: Javascript 和 jQuery 两者不能混为一谈。Javascript 动画很快,而 jQuery 动画很慢。为什么呢?因为尽管 jQuery 异常强大,但是它的设计目标并不是一个高效的动画引擎:

  • jQuery 不能避免 layout thrashing (有人喜欢将其翻译为“布局颠簸”,会导致多余relayout/reflow),因为它的代码不仅仅用于动画,它还用于很多其他场景。
  • jQuery的内存消耗较大,经常会触发垃圾回收。而垃圾回收触发时很容易让动画卡住。
  • jQuery使用了setInterval而不是 reqeustAnimationFrame(RAF),因为 RAF 会在窗口失去焦点时停止触发,这会导致jQuery的bug。(目前jQuery已经使用了RAF)

注意 layout thrashing 会导致动画在开始的时候卡顿,垃圾回收的触发会导致动画运行过程中的卡顿,不使用 RAF 则会导致动画帧率低。

实现样例

为了避免layout thrashing,我们需要批量访问和更新DOM。

var currentTop,

currentLeft;

/* 有 layout thrashing. */

currentTop = element.style.top; /* 访问 */

element.style.top = currentTop + 1; /* 更新 */

currentLeft = element.style.left; /* 访问 */

element.style.left = currentLeft + 1; /* 更新 */

/* 没有 layout thrashing. */

currentTop = element.style.top; /* 访问 */

currentLeft = element.style.left; /* 访问 */

element.style.top = currentTop + 1; /* 更新 */

element.style.left = currentLeft + 1; /* 更新 */

在更新操作之后的访问操作会强制浏览器重新计算页面元素的样式(因为要将更新的样式应用上去才能获取正确的值)。这在一般操作下没多大的性能损失,但是放在间隔仅仅16ms的动画中则会导致显著的性能开销。只需要稍微改动下操作的顺序就可以大大提高动画的性能。

类似地,使用 RAF 也不会让你大量重构代码。让我们来比较下使用 RAF 和使用 setInterval 的区别:

var startingTop = 0;

/* setInterval: Runs every 16ms to achieve 60fps (1000ms/60 ~= 16ms). */

setInterval(function() {

/* Since this ticks 60 times a second, we divide the top property‘s increment of 1 unit per 1 second by 60. */

element.style.top = (startingTop += 1/60);

}, 16);

/* requestAnimationFrame: Attempts to run at 60fps based on whether the browser is in an optimal state. */

function tick () {

element.style.top = (startingTop += 1/60);

}

window.requestAnimationFrame(tick);

你只需要稍微修改下代码来使用 RAF,就可以让你的动画性能有巨大的提高。

CSS Transition

CSS transition 的动画逻辑是由浏览器来执行,所以它的性能能够比 jQuery 动画好。它的优势体现在:

  1. 通过优化 DOM 操作,避免内存消耗来减少卡顿
  2. 使用与 RAF 类似的机制
  3. 强制使用硬件加速 (通过 GPU 来提高动画性能)

然而实际上Javascript也可以使用这些优化。GSAP 已经做这些优化很久了。Velocity.js 是一个新兴的动画引擎,它不仅仅做了这些优化,甚至走的更远些。我们稍后会谈到这些。

面对事实,让 Javascript 动画得以媲美 CSS 动画的性能只是我们伟大计划的第一步。第二步才是重头戏,要让 Javascript 动画比 CSS 动画还要快!

让我们来看看 CSS 动画库的缺陷吧:

  • Transition 强制使用了 GPU 的硬件加速。导致浏览器一直处于高负荷运转的状态,这反而会让动画变的卡顿。这在移动浏览器上更为严重。(特别要说明的是,当数据在浏览器的主线程和合成线程之间频繁传输的时候特别消耗性能,故容易导致卡顿。某些 CSS 属性,不会受到影响。Adobe 的博客谈到过这个问题。
  • IE 10以下的浏览器不支持 transition。而目前 IE8 和 IE9 还是很流行的。
  • transition 不能完全被 Javascript 控制(只能通过 Javascript 来触发 transition),因为浏览器不知道如何同时让 Javascript 控制动画又同时优化动画的性能。

反过来说: 基于 Javascript 可以决定什么时候启用硬件加速,它可以支持全版本的 IE,并且它完全可以进行批量动画的优化。

我的建议是:当你只在移动平台上开发,并且动画只是简单的状态切换,那么适合用纯 CSS transition。在这种情况下,transition 是高性能的原生支持方案。它可以让你将动画逻辑放在样式文件里面,而不会让你的页面充斥 Javascript 库。然而如果你在设计很复杂的富客户端界面或者在开发一个有着复杂UI状态的 app。那么我推荐你使用一个动画库,这样你的动画可以保持高效,并且你的工作流也更可控。有一个特别的库做的特别棒,它可以用 Javascript 控制 CSS transition。这就是 Transit。

Javascript 动画

所以 Javascript 可以比 CSS transition 性能更好。但是它到底有多块呢?它快到足够可以构建一个3D 动画的demo,通常需要用到 WebGL 才能完成。并且它快到足够搭建一个多媒体小动画,通常需要 Flash 或者 After Effects 才能完成。并且它还快到可以构建一个虚拟世界,通常需要 canvas 才能完成。

为了更直接的来比较主流动画库的性能,包括 Transit(使用了 CSS transition),让我们打开Velocity的官方文档。

之前那个问题还在:Javascript 是如何达到高性能的呢?下面是一个列表,列举了基于 Javascript 的动画库能做的事情:

  • 同步DOM -> 在整个动画链中微调堆栈以达到最小的layout thrashing。
  • 缓存链式操作中的属性值,这样可以最小化DOM的查询操作(这就是高性能 DOM 动画的阿喀琉斯之踵)
  • 在同一个跨同层元素的调用中缓存单位转化比率(例如px转换成%、em等等单位)
  • 忽略那些变动小到根本看不出来的DOM更新

让我们重新温习下之前学到的关于layout thrashing的知识点。Velocity.js 运用了这些最佳实践,缓存了动画结束时的属性值,在紧接的下一次动画开始时使用。这样可以避免重新查询动画的起始属性值。

$element

/* Slide the element down into view. */

.velocity({ opacity: 1, top: "50%" })

/* After a delay of 1000ms, slide the element out of view. */

.velocity({ opacity: 0, top: "-50%" }, { delay: 1000 });

在上面的样例中,第二次调用 Velocity 时已经知道了 opacity 的起始值为 1,top 的值为 50%。

浏览器也可以使用与此类似的优化,但是要做这些事情太过激进,使用场景也会受到限制,开发者就有可能会写出有bug的动画代码。jQuery就是因为这个原因没有使用RAF(如上所说),浏览器永远不会强行实施可能打破规范或者可能偏离期望行为的优化。

最后,让我们来比较下两个Javascript框架(velocity.js 和 GSAP)。

  • GASP 是一个快速且功能丰富的动画平台。Velocity则更为轻量级,它大大地改善了UI动画性能和工作流程。
  • GSAP 需要付费才能用于商业产品。Velocity 是完全免费的,它使用了自由度极高的 MIT 协议。
  • 性能方面,两者几乎相当,很难区分胜负。

我个人推荐在你需要如下功能时使用 GSAP:精确控制时间(例如 remapping,暂停/继续/跳过),或者需要动作(例如:贝赛尔曲线路径),又或者复杂的动画组合/队列。这些特性对游戏开发或者复杂的应用很重要,但是对普通的 web app 的 UI 不太需要。

Velocity.js

之前提到了 GSAP 有着丰富的功能,但这不代表 Velocity 的功能简单。相反的,Velocity 在 zip 压缩之后只有 7kb,它不仅仅实现了 jQuery animate 方法的所有功能,还包含了 颜色、transforms、loop、easings、class 动画和滚动动画等功能。

简单的说就是 Velocity 包含了 jQuery、 jQuery UI 和 CSS transition 的功能。

更进一步从易用性的角度来讲,Velocity 使用了 jQuery 的$.queue() 方法,因此可以无缝过渡到 jQuery 的$.animate()、$.fade()和$.delay()方法。并且 Velocity 的语法和$.animate()一摸一样,所以我们根本不需要修改页面的现有代码。

让我们快速过一下 Velocity.js 的例子:

$element

.delay(1000)

/* Use Velocity to animate the element‘s top property over a duration of 2000ms. */

.velocity({ top: "50%" }, 2000)

/* Use a standard jQuery method to fade the element out once Velocity is done animating top. */

.fadeOut(1000);

如下是一个高级用法:滚动网页到当前元素并且旋转元素。这样的动画只需要简单的几行代码:

$element

/* Scroll the browser to the top of this element over a duration of 1000ms. */

.velocity("scroll", 1000)

/* Then rotate the element around its Y axis by 360 degrees. */

.velocity({ rotateY: "360deg" }, 1000);

总结

Velocity 的目标是成为 DOM 动画领域性能最好易用性最高的库。这篇文章主要关注了性能方面。易用性方面可以前往 VelocityJS.org 了解。

在结束之前,请记住一个高性能的 UI 绝不仅仅是选择一个正确的动画库。页面上的其他代码也需要优化。可以看看Google那些非常棒的演讲:

  • Jank Free
  • Rendering Without Lumps
  • Faster Websites

【今日微信公号推荐↓】

更多推荐请看值得关注的技术和设计公众号

其中推荐了包括技术设计极客 和 IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!

时间: 2024-07-30 23:44:19

CSS vs JS动画:谁更快?的相关文章

CSS 和 JS 动画哪个更快

基于Javascript的动画暗中同CSS过渡效果一样,甚至更加快,这怎么可能呢?而Adobe和Google持续发布的富媒体移动网站的性能可媲美本地应用,这又怎么可能呢? 本文逐一遍览了基于Javascript的DOM动画库,如Velocity.js和GSAP,看其是如何比jQuery和CSS动画效果更具性能的. jQuery 让我们先从基础的开始: JavaScript 和 jQuery 被错误的混为一谈了. JavaScript 动画是很快的. jQuery 把它放慢了下来.为什么?因为 —

CSS vs. JS Animation: 哪个更快

CSS vs. JS Animation: 哪个更快? CSS vs. JS Animation: 哪个更快? 基于JavaScript的动画竟然已经默默地比CSS的transition动画快了?而且,Adobe和 Google竟然一直在发布可以媲美原生应用的富媒体移动站点? 这篇文章将会逐点讲解基于JavaScript的DOM动画库,比如Velocity.js和GSAP,是如何比jQuery和基于CSS的动画库高效的. jQuery 让我们先从这个事实开始:JavaScript和jQuery被

CSS VS JS动画,哪个更快[译]

英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js动画库.在<Javascript网页动画设计>一书中对这个库有很多更具体的剖析,对Velocity及JS动画感兴趣的可以一看. 基于Javascript的动画怎么可能总是和 CSS transition 一样快,甚至更快呢?到底是什么秘密呢?Adobe 和 Google 是怎么做到让他们的富媒体移

JQuery动画插件Velocity.js发布:更快的动画切换速度

5月3日,Julian在其GitHub上发布了Velocity.js.Velocity.js是一款动画切换的jQuery插件,它重新实现了jQuery的$.animate()方法从而加快动画切换的速度.Velocity.js只有7k的大小,它不仅包含了$.animate()的所有功能,并且还包含了颜色切换.转换(transform).循环.缓动.CSS切换.Scroll功能,它是jQuery. jQuery UI.CSS变换 在动画方面的最佳组合.Velocity.js支持IE8+.Chrome

How Javascript works (Javascript工作原理) (十三) CSS 和 JS 动画底层原理及如何优化其性能

个人总结:读完这篇文章需要20分钟. 这是 JavaScript 工作原理的第十三章. 概述 正如你所知,动画在创建令人叹服的网络应用中扮演着一个关键角色.由于用户越来越注重用户体验,商户开始意识到完美,令人愉悦的用户体验的重要性,结果网络应用变得越来越重并且拥有更多动态交互的功能.这就要求网络应用提供更加复杂的动画来实现平滑的状态过渡贯穿于用户的使用过程当中.现在,这已经司空见惯.用户变得越来越挑剔,他们潜意识期许可以获得快速响应和良好交互的用户界面. 然而,让界面具有动画效果不一定是件简单的

CSS VS JS动画,哪个更快

JQuery 让我们从最基础的开始说起: Javascript 和 jQuery 两者不能错误的混为一谈.Javascript 动画很快,而 jQuery 动画却慢下来.为什么呢?因为尽管 jQuery 非常强大,但是它的设计目标并不是一个高效的动画引擎: 1.JQuery不能避免layout thrashing,由于它不仅仅要服务于动画,也需要用于其他场景. 2.JQuery的内存消耗会频繁的触发垃圾回收机制,而垃圾回收会让动画暂时卡住. 3.JQuery使用了setInterval而不是re

自从用了Less 编写css,你比以前更快了~(sublime编译)

之所以用这个标题呢,主要是最近调侃杰伦太有意思了. 好吧,开个玩笑而已. 如果你了解过Less,并对之很熟悉,就不用往下看了. 如果你没用过,恭喜,这是一个入门级的教程,学会了它,可以为你节省10%的绳命. 首先,我们得知道Less能干什么.如: @width:300px; @fonts:12px bold "宋体,Verdana"; .block-header{ color:#5c5c5c; .elem-title{ font:@fonts; width:@width; } .ele

更轻更快的Vue.js 2.0与其他框架对比(转)

更轻更快的Vue.js 2.0 崭露头角的JavaScript框架Vue.js 2.0版本已经发布,在狂热的JavaScript世界里带来了让人耳目一新的变化. Vue创建者尤雨溪称,Vue 2.0 在性能上有显著的提升,同时保持轻量的文件下载: 渲染层基于一个轻量级的Virtual DOM实现进行了重写,该Virtual DOM实现fork自snabbdom.新的渲染层相比v1带来了巨大的性能提升,也让Vue 2.0成为了最快速的框架之一. 根据1.0到2.0迁移指南,“大约90%的API是相

JS动画与CSS动画

一.JS动画(setInterval setTimeOut requestAnimationFrame) 优点: 1)过程控制能力强.可以对动画工程进行精准的控制,暂停.取消.开始.终止都可以. 2)动画效果多.炫酷.有一些效果是CSS动画所不能实现的 3)兼容性比较高 缺点: 1)由于JS是通过不断的操作DOM和CSS的属性来实现动画效果的,这需要不断的重排(reflow)和重绘(repaint),非常消耗浏览器的内存.(在PC端有浏览 器可以分配的内存比较大,动画的重排(reflow)和重绘