Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >CSS vs JS动画:谁更快?

CSS vs JS动画:谁更快?

作者头像
mmzhou
发布于 2018-08-01 10:50:09
发布于 2018-08-01 10:50:09
2.2K00
代码可运行
举报
文章被收录于专栏:前端小作坊前端小作坊
运行总次数:0
代码可运行

CSS vs JS动画:谁更快?

这篇文章翻译自 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。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 的区别:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 运用了这些最佳实践,缓存了动画结束时的属性值,在紧接的下一次动画开始时使用。这样可以避免重新查询动画的起始属性值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$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 的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$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);

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$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那些非常棒的演讲:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
✍️浏览器渲染原理深度拆解:为什么你的动画总是卡顿?
你以为浏览器只是简单地将HTML/CSS/JS转换成像素?其实背后隐藏着一套精密流水线:
Jimaks
2025/05/26
1110
✍️浏览器渲染原理深度拆解:为什么你的动画总是卡顿?
搞定这些疑难杂症,向css3动画说yes
本文篇幅比较长,涉及到的知识点也比较多,如3d,动画性能,动画js事件等,参考文献及demo展示也比较多,所以建议pc阅读效果更佳。 动画库 到现在来说css3动画也不是什么新技术,既然是要搞定它,好歹我们也得先看下别人做的一些东西吧,所以在此先向各位推荐几个比较好用的动画库: animate.css effeckt hover.css animatable 关于css3动画不得不说的几个属性 看完上面那些动画库,心痒就不如行动了。 说起css3动画,有一个属性我们绝对避不开了,那就是transform这个
IMWeb前端团队
2018/01/15
2.1K0
搞定这些疑难杂症,向css3动画说yes
【前端动画】实现动画的6种方式
javascript 实现动画通常会导致页面频繁性重排重绘,消耗性能,一般应该在桌面端浏览器。在移动端上使用会有明显的卡顿。(❤️ 现在关注【前端修罗场】,后台回复【666】,即可获取一份【免费的优质学习资料】,一起学习,一起进步~)
前端修罗场
2023/10/07
5680
WEB动画的几种实现方式
WEB 的动画实现多种多样,随着 H5 的发展,实现动画的方式越来越多了。初步统计实现动画的方式有以下一些方式实现
chuchur
2022/10/25
2.5K0
WEB动画的几种实现方式
33.Vue-使用第三方animate.css类库实现动画
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。 包括以下工具:
Devops海洋的渔夫
2020/05/04
6.9K0
深度剖析浏览器渲染性能原理,你到底知道多少
作者:齐修_qixiuss https://www.jianshu.com/p/a32b890c29b1
用户4456933
2021/06/01
1.5K0
深度剖析浏览器渲染性能原理,你到底知道多少
「Web Animation API 专题」用原生JS制作一个图片随机移动的动画
当我们谈及网页动画时,自然联想到的是 CSS3 动画、JS 动画、SVG 动画 等技术以及 jQuery.animate() 等动画封装库,根据实际动画内容设计去选择不同的实现方式,然而,每个现行的动画技术都存在一定的缺点,如 CSS3动画必须通过JS去获取动态改变的值,一个动画效果分散在css文件和js文件里不好维护,setInterval 的时间往往是不精确的而且还会卡顿,引入额外的动画封装库也并非对性能敏感的业务适用。
前端达人
2019/08/02
4.1K0
「Web Animation API 专题」用原生JS制作一个图片随机移动的动画
让你的网页更丝滑(一)
前段时间,我将精力专注在Web性能领域;在这个领域下有个重要的课题是如何让网页更丝滑(流畅)。
coder_koala
2019/10/15
1.7K0
让你的网页更丝滑(一)
34. Vue-使用JavaScript 钩子函数实现半场动画
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。 包括以下工具:
Devops海洋的渔夫
2020/06/15
1.5K0
34. Vue-使用JavaScript 钩子函数实现半场动画
[译]SVG动画简介
你可以把这篇文章看做通往精通SVG动画之路的第一步,里面的链接资源也是很好的学习资料。所以赶紧收藏本文然后开始你的精通SVG之旅吧。
小刀c
2022/08/16
1.7K0
[译]SVG动画简介
Web高性能动画及渲染原理(1)CSS动画和JS动画
Web动画的本质是元素状态改变造成的样式变更,CSS动画和JS动画的区别并不是由语言来决定的,而是由两者的特点和适用场景来判断的。CSS动画简洁高效,提升交互体验而编写的代码可以轻松地和主要业务逻辑之间实现隔离,开发中建议优先使用;而当你需要更丰富的缓动函数,多对象关联动画或是需要在动画执行的特定时间点关联一些其他的业务逻辑等需要细节控制的场景中,JS动画就会显得更加清晰且易维护,两者从来都不是非黑即白的选项。
大史不说话
2019/10/16
7.8K0
Web高性能动画及渲染原理(1)CSS动画和JS动画
「Web Animation API 专题」纯手工撸一个图片随机移动的动画
当我们谈及网页动画时,自然联想到的是 CSS3 动画、JS 动画、SVG 动画 等技术以及 jQuery.animate() 等动画封装库,根据实际动画内容设计去选择不同的实现方式,然而,每个现行的动画技术都存在一定的缺点,如 CSS3动画必须通过JS去获取动态改变的值,一个动画效果分散在css文件和js文件里不好维护,setInterval 的时间往往是不精确的而且还会卡顿,引入额外的动画封装库也并非对性能敏感的业务适用。
前端达人
2019/07/31
1.8K0
「Web Animation API 专题」纯手工撸一个图片随机移动的动画
制作60fps的高性能动画
说到web的高性能动画,这部分内容其实已经是老生常谈的了,不过其中还是有不少比较新的而且非常实用的内容可以和大家分享一下。
QQ音乐前端团队
2018/09/25
2.8K2
要实现60FPS动画, 你需要了解这些
60FPS, 即每秒渲染60帧, 每一帧的间隔时间为 1000ms / 60 = 16.666ms
木子星兮
2020/09/15
1.4K0
要实现60FPS动画, 你需要了解这些
2020已经过去五分之四了,你确定还不来了解一下JS的rAF?
不会吧,不会吧,现在都2020年了不会还真人有人不知道JS的rAF吧??? rAF 简介 rAF是requestAnimationFrame的简称; 我们先从字面意思上理解requestAnimati
Tz一号
2020/10/26
1.2K0
2020已经过去五分之四了,你确定还不来了解一下JS的rAF?
前端动画实现总结
SVG动画由SVG元素内部的元素属性控制,一般通过一下几个元素控制: - 用于控制动画延时 - 对属性的连续改变进行控制 - 颜色变化,但用就能控制 - 控制如缩放、旋转等几何变化 - 控制SVG内元素的移动路径
江米小枣
2020/06/16
1.4K0
干货 | 携程火车票7个优化动画性能的方法
携程火车票营销页使用 css 制作动画很多年了,这大大提高了动画给予页面丰富的视觉体验。不过,在开发的过程中,也遇到了一些性能相关问题和用户反馈,比如头部动画卡顿、页面打开时间较长、页面打开后部分数据加载时间较长等问题。为解决这些问题,我们借助性能检测工具定位问题,并查阅源码、文档等资源解决问题,形成了这篇文章。
携程技术
2023/09/06
3150
干货 | 携程火车票7个优化动画性能的方法
JavaScript动画基本原理
在现在做页面很多时候都会用上动画效果。比如下拉菜单,侧边搜索栏,层的弹出与关闭等等。通常我们实现这些动画效果可以采用 JavaScript与CSS3两种方式来实现。本文主要介绍JavaScript动画,CSS3的动画下次在总结。对于JavaScript动画 目前有很多的动画插件库,如: Jquery等等.以下就简单介绍以下JavaScript动画的实现原理。
全栈程序员站长
2022/11/03
1.2K0
好玩又实用的19个JavaScript动画库
今天我们来看看2019年的一些伟大的JavaScript动画库。在2002年左右,我们使用Flash来制作网络动画。而在2008年,由Flash制作的网站是非常受欢迎(Flash网页游戏风靡一时)。
Javanx
2019/09/04
3.5K0
好玩又实用的19个JavaScript动画库
只听说过CSS in JS,怎么还有JS in CSS?
CSS in JS是一种解决css问题想法的集合,而不是一个指定的库。从CSS in JS的字面意思可以看出,它是将css样式写在JavaScript文件中,而不需要独立出.css、.less之类的文件。将css放在js中使我们更方便的使用js的变量、模块化、tree-shaking。还解决了css中的一些问题,譬如:更方便解决基于状态的样式,更容易追溯依赖关系,生成唯一的选择器来锁定作用域。尽管CSS in JS不是一个很新的技术,但国内的普及程度并不高。由于Vue和Angular都有属于他们自己的一套定义样式的方案,React本身也没有管用户怎样定义组件的样式[1],所以CSS in JS在React社区的热度比较高。
疯狂的技术宅
2021/04/23
7.2K0
只听说过CSS in JS,怎么还有JS in CSS?
相关推荐
✍️浏览器渲染原理深度拆解:为什么你的动画总是卡顿?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验