首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >前端-CSS3 动画卡顿性能优化解决方案

前端-CSS3 动画卡顿性能优化解决方案

作者头像
grain先森
发布于 2019-03-29 03:03:47
发布于 2019-03-29 03:03:47
3.2K0
举报
文章被收录于专栏:grain先森grain先森

来源:趁你还年轻 segmentfault.com/a/1190000013045035

最近在开发小程序,与vue类似,它们都有生命周期这回事。

1、onLoad 监听页面加载

2、onReady 监听页面初次渲染完成

3、onShow 监听页面显示

到底是什么意思?

所以这又触碰到了我的知识盲区,不过项目在磕磕绊绊中完成的差不多了,但是遇到了CSS3动画渲染的性能问题,所以我也是被逼的,再回过头来从浏览器渲染网页的流程出发,去找动画卡顿的症结。

浏览器渲染网页的流程如下:

1、使用 HTML 创建文档对象模型(DOM)

2、使用 CSS 创建 CSS 对象模型(CSSOM)

3、基于 DOM 和 CSSOM 执行脚本(Scripts)

4、合并 DOM 和 CSSOM 形成渲染树(Render Tree)

5、使用渲染树布局(Layout)所有元素

6、渲染(Paint)所有元素

可以结合Alon的这篇前端性能优化和安卓开发者选项的显示页面布局。

安卓开发者选项的显示页面布局

如何判断手机app是native,webview还是hybird?

简单说下,app中的一大块是白色的没有红线标记出来的,但是上面有按钮,图片等时,就是webview,也就是通过一个伪浏览器去请求到的数据,断网时打开app没有任何东西显示在上面

onLoad 监听页面加载

在渲染完界面之后,也就是通过.json中的配置项生成native界面后,开始渲染webview的部分,一个页面只会调用一次。

onReady 监听页面初次渲染完成

一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。

onShow 监听页面显示

每次打开页面都会去调用其中的函数。

我们的动画应该放在哪里?

应该放在onShow里,因为这样我每次打开都能看到动画。

为什么会卡顿?

有一个前提必须要提,前端开发者们都知道,浏览器是单线程运行的。但是我们要明确以下几个概念:单线程,主线程和合成线程。

虽然说浏览器执行js是单线程执行(注意,是执行,并不是说浏览器只有1个线程,而是运行时,runing),但实际上浏览器的2个重要的执行线程,这 2 个线程协同工作来渲染一个网页:主线程和合成线程。

一般情况下,主线程负责:运行 JavaScript;计算 HTML 元素的 CSS 样式;页面的布局;将元素绘制到一个或多个位图中;将这些位图交给合成线程。

相应地,合成线程负责:通过 GPU 将位图绘制到屏幕上;通知主线程更新页面中可见或即将变成可见的部分的位图;计算出页面中哪部分是可见的;计算出当你在滚动页面时哪部分是即将变成可见的;当你滚动页面时将相应位置的元素移动到可视区域。

那么为什么会造成动画卡顿呢?

原因就是主线程和合成线程的调度不合理。

下面来详细说一下调度不合理的原因。

在使用height,width,margin,padding作为transition的值时,会造成浏览器主线程的工作量较重,例如从margin-left:-20px渲染到margin-left:0,主线程需要计算样式margin-left:-19px,margin-left:-18px,一直到margin-left:0,而且每一次主线程计算样式后,合成进程都需要绘制到GPU然后再渲染到屏幕上,前后总共进行20次主线程渲染,20次合成线程渲染,20+20次,总计40次计算。

主线程的渲染流程,可以参考浏览器渲染网页的流程:

1、使用 HTML 创建文档对象模型(DOM)

2、使用 CSS 创建 CSS 对象模型(CSSOM)

3、基于 DOM 和 CSSOM 执行脚本(Scripts)

4、合并 DOM 和 CSSOM 形成渲染树(Render Tree)

5、使用渲染树布局(Layout)所有元素

6、渲染(Paint)所有元素**

也就是说,主线程每次都需要执行Scripts,Render Tree ,Layout和Paint这四个阶段的计算。

而如果使用transform的话,例如tranform:translate(-20px,0)到transform:translate(0,0),主线程只需要进行一次tranform:translate(-20px,0)到transform:translate(0,0),然后合成线程去一次将-20px转换到0px,这样的话,总计1+20计算。

可能会有人说,这才提升了19次,有什么好性能提升的?

假设一次10ms。

那么就减少了约190ms的耗时。

会有人说,辣鸡,才190ms,无所谓。

那么如果margin-left是从-200px到0呢,一次10ms,10ms*199≈2s。

还会有人说,辣鸡,也就2s,无所谓。

你忘了单线程这回事了吗?

如果网页有3个动画,3*2s=6s,就是6s的性能提升。

由于数据是猜测的,所以暂时不考虑其真实性,文章后面我使用chrome devtools的performance做了一个实验。

要知道,在"客户至上"的今天,好的用户体验是所有产品的必须遵守的一条规则,无论是对于开发者还是产品经理,追求极致的性能都是我们打造一个好的产品所必备的品质。

可能看了我的略不专业的分析后,大家对主线程,合成线程以及它们在2种性能不同动画方案上的工作流程还不是很了解,可以去看一篇翻译过来的博客(英文原版链接已经失效了):深入浏览器理解CSS animations 和 transitions的性能问题

这篇文章完美讲述了浏览器主线程和合成线程的区别,并且举了一个高度从100px变化到200px的2种动画方案的对比,对主线程和合成线程的整个工作流程做了很详尽的讲解,真心建议认真阅读一遍。

回过头来总结下,css3动画卡顿的解决方案:

在使用css3 transtion做动画效果时,优先选择transform,尽量不要使用height,width,margin和padding。

transform为我们提供了丰富的api,例如scale,translate,rotate等等,但是在使用时需要考虑兼容性。但其实对于大多数css3来说,mobile端支持性较好,desktop端支持性需要格外注意。

补充:为了增强本文的说服力,特地回家做了一个实验,代码如下。

<!DOCTYPE html>

<html>

<head>

 <meta charset="utf-8" />

 <meta http-equiv="X-UA-Compatible" content="IE=edge">

 <title>Page Title</title>

 <meta name="viewport" content="width=device-width, initial-scale=1">

 <style>

   .margin-transition{

     /* margin-left: 0; */

     background: rgba(0,0,255,0.3);

     transition: margin-left 1s;

   }

   .transform-transition{

     /* transform: translate(0,0); */

     background: rgba(0,255,0,0.3);

     transition: transform 1s;

   }

   .common{

     height: 300px;

     width: 300px;

   }

 </style>

</head>

<body>

 <div class="margin-transition common" id="marginTransition">

   <p>transition:margin-left 1s</p>

 </div>

 <div class="transform-transition common" id="transformTransition">

     <p>transition:tranform 1s</p>

 </div>

 <button id="control">见证奇迹</button>

 <script>

     var btn = document.getElementById('control');

     var marginTransition = document.getElementById('marginTransition');

     var transformTransition = document.getElementById('transformTransition');

     btn.addEventListener("click",function(){

       console.log(marginTransition.style,transformTransition.style)

       marginTransition.style.marginLeft = "500px";

       transformTransition.style.transform = "translate(500px,0)"

     })

 </script>  

</body>

</html>

我将主要借助chrome devtools的performance工具对比二者的性能差异。

先来看margin动画,动态修改DOM节点的margin-left值从0到500px;。

transition: margin-left 1s;

再来看下transform动画,动态修改DOM节点的transform值从translate(0,0)到translate(500px,0)。

transition: transform 1s;

可能图片不是很好地能说明性能差异,那么我们来列一张耗时对比表,方便我们计算。

耗时

margin

transform

Summery

3518ms

2286ms

Scripting

1.8ms

2.9ms

Rendering

22.5ms

6.9ms

Painting

9.7ms

1.6ms

Other

39.3ms

25.2ms

Idle( browser is waiting on the CPU or GPU to do some processing)

3444.4ms

2249.8ms

GPU使用率

4.1MB

1.7MB

通过上表我们可以计算出明margin,transform与transition组合实现CSS3动画效果时的性能差异参数。

关键性能参数

margin

transform

实际动画耗时(总时间 减去 空闲时间)

73.6ms

36.2ms

计算得出,transform动画耗时约等于margin动画耗时的0.49倍,性能优化50%。

由于我对Other的所做的具体事情不是很清楚,所以这里的实际动画时间也有可能还要减掉Other中的时间,下表是我们减掉后的数据。

关键性能参数

margin

transform

实际动画耗时(总时间 减去 其他时间和空闲时间)

34.3ms

11ms

计算得出,transform动画耗时约等于margin动画耗时的0.32倍,性能优化接近70%。

也就是说,无论我们减去还是不减去Other的时间,我们采用transform实现动画的方式都比margin动画快。

不精确的得出一个小结论:transform比margin性能好50%~70%

虽然会有50%~70%的性能提升,但是需要注意硬件差异,硬件好的情况下可能不能发现卡顿或者其他的一些性能上的问题。

例如在开发小程序的过程中,模拟器是位于desktop端的,因此它的硬件性能性能更好,例如CPU,GPU。但是一旦在mobile端运行,例如ios或者android上运行时,就可能会出现性能问题,这就是因为移动端的硬件条件逊于PC端导致的。

所以说,性能问题是一直存在的,只不过硬件差异会导致性能影响的程度不同。

所以我们再次回过头来,总结出css3动画卡顿的解决方案:

在使用css3 transtion做动画效果时,优先选择transform,尽量不要使用height,width,margin和padding。

That's it !

参考

1、http://sy-tang.github.io/2014/05/14/CSS+animations+and+transitions+performance-+looking+inside+the+browser/

2、http://jinlong.github.io/2017/05/08/optimising-the-front-end-for-the-browser/

3、http://blog.csdn.net/yeana1/article/details/52756871

4、https://www.jianshu.com/p/b70b72de3c32

5、https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/

6、http://blogs.adobe.com/webplatform/2014/03/18/css-animations-and-transitions-performance/

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

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

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
✍️浏览器渲染原理深度拆解:为什么你的动画总是卡顿?
你以为浏览器只是简单地将HTML/CSS/JS转换成像素?其实背后隐藏着一套精密流水线:
Jimaks
2025/05/26
1580
✍️浏览器渲染原理深度拆解:为什么你的动画总是卡顿?
如何快速上手基础的CSS3动画
说起CSS3动画,就必须说说 transform,translate,transition,animation这4个属性,transform主要定义元素的动作,比如旋转、倾斜、位移等,translate是transform里面的属性,用于2D/3D位移。后2个主要对动作进行描述,动画时间、速度曲线、次数等。
Javanx
2019/09/04
4480
如何快速上手基础的CSS3动画
13·灵魂前端工程师养成-CSS动画
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
DriverZeng
2022/09/26
1.7K0
13·灵魂前端工程师养成-CSS动画
搞定这些疑难杂症,向css3动画说yes
本文篇幅比较长,涉及到的知识点也比较多,如3d,动画性能,动画js事件等,参考文献及demo展示也比较多,所以建议pc阅读效果更佳。 动画库 到现在来说css3动画也不是什么新技术,既然是要搞定它,好歹我们也得先看下别人做的一些东西吧,所以在此先向各位推荐几个比较好用的动画库: animate.css effeckt hover.css animatable 关于css3动画不得不说的几个属性 看完上面那些动画库,心痒就不如行动了。 说起css3动画,有一个属性我们绝对避不开了,那就是transform这个
IMWeb前端团队
2018/01/15
2.2K0
搞定这些疑难杂症,向css3动画说yes
CSS3动画性能优化集
在浏览器开始渲染页面,或者长时间执行某个 JS 时,主线程会一直在忙碌状态,此时对于用户的任何输入或是操作都不会有所响应。
2Broear
2024/03/12
2480
CSS3强制启用 GPU 加速渲染 CSS3 动画
css3 transform:translateZ(0)解决一个存在已久并早已知悉解决方案的渲染问题… 最终,只用了一小段的css代码就解决了
2Broear
2024/03/12
3840
CSS动画的性能优化
在Web页面中使用动画效果已经不是什么稀奇的事情了。但凡优秀的UI界面都会有一些点缀用的动画效果。举个例子,Stripe Checkout小组通过UI动画效果来增强支付体验。
mmzhou
2018/08/06
1.9K0
CSS动画的性能优化
【前端动画】实现动画的6种方式
javascript 实现动画通常会导致页面频繁性重排重绘,消耗性能,一般应该在桌面端浏览器。在移动端上使用会有明显的卡顿。(❤️ 现在关注【前端修罗场】,后台回复【666】,即可获取一份【免费的优质学习资料】,一起学习,一起进步~)
前端修罗场
2023/10/07
6180
CSS3动画-抛物线运动
今天来说下CSS3动画,目标是让一个方块做抛物线运动。主要用到的CSS3属性有animation,transform,@keyframes,transition等。 ---- Animation版-0 我们先建立一个HTML文件,test.html: <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" href="animation.css"/> </head> <body> <div class="item"></d
Bob.Chen
2018/05/02
1.8K0
CSS3动画-抛物线运动
CSS animation和transition的性能探究
你可能已经在你的项目中用上了CSS Animation和CSS transition。如果还没有用上,那你有点out了。快去看下CSS-Trick上的这两篇关于animation和transition的文章。你在使用中一定发现了有些动画很流畅,而有些则很卡。为什么呢?
mmzhou
2018/08/06
1.4K0
CSS animation和transition的性能探究
CSS3动画,为你带来极致的视觉体验!
HTML5学堂:随着网络的发展,浏览器具有更强的渲染与高级代码的执行能力。所以在当前,大量的动画效果由原来的JavaScript制作正慢慢的被CSS3所替代,究其原因在于CSS3的性能会比JS的性能来的好,并且CSS3动画为用户带来了强大而又震撼的效果,为开发者带来了简单的书写方式。 本文主要内容 1、前言 2、实现动画的前奏 3、CSS3动画的语法 4、实例解析 5、总结 1、前言 CSS3属性中有关于制作动画的三个属性:Transform、Transition、Animation;之前一起学习了Tran
HTML5学堂
2018/03/13
1.4K0
CSS3动画,为你带来极致的视觉体验!
浏览器的渲染流程--重排、重绘、合成
定义: 当通过JS或css改变了元素的宽度、高度等,修改了元素的几何位置属性,那么浏览器会触发重新布局,解析之后的一系列子阶段,这个过程就叫重排。无疑, 重排需要更新完整的渲染流水线,所以开销也是最大的。
用户7741497
2022/03/06
1.2K0
纯CSS3绘制的逼真,呆萌,超酷的CSS3动画纯CSS3人物行走动画 逼真炫酷CSS3动画纯CSS3绘制的小猫笑脸动画 超呆萌纯CSS3绘制可爱小男孩动画 超酷面部表情
纯CSS3人物行走动画 逼真炫酷CSS3动画 CSS3实在是太强大了,今天分享的CSS3动画非常神奇,它可以模拟人物行走,而且人物行走动画非常逼真。人物行走时的跨步动画时多张图片重叠实现的。有了这个
wblearn
2018/08/27
1.7K0
纯CSS3绘制的逼真,呆萌,超酷的CSS3动画纯CSS3人物行走动画 逼真炫酷CSS3动画纯CSS3绘制的小猫笑脸动画 超呆萌纯CSS3绘制可爱小男孩动画 超酷面部表情
分享 | 前端性能优化(CSS动画篇)
最近拜读了一下html5rocks上几位大神写的一篇关于CSS3动画性能优化的文章,学到了很多,在这里记录一下,其中的知识都是来源于这俩篇文章,我只是截取了其中比较关注的内容出来,原文地址High Performance Animations及Accelerated Rendering in Chrome
疯狂的技术宅
2019/03/28
2.1K0
will-change提高动画性能与页面滚动性能
视差滚动现在不是挺流行的嘛,然后Chris Ruppel当其使用background-attachment: fixed实现背景图片不随滚动条滚动而滚动效果的时候,发现,页面的绘制性能掉到了每秒30帧,这种帧频人眼已经可以感觉到一定的顿挫感了。
javascript.shop
2019/09/04
8720
will-change提高动画性能与页面滚动性能
为什么 CSS 动画比 JavaScript 高效?
讲到动画,当然是非常有意思的啦,你可以往上滑一下,看看上面的封面图,是不是相当的炫酷,以为我是代码写出来的吗?
小丞同学
2021/08/31
1K0
为什么 CSS 动画比 JavaScript 高效?
疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!
通常来讲,当动画的每秒帧数低于 12 (即 12 FPS 以下)时,我们的大脑就能快速从动画中区分出一些静止的图片,所以此时的动画并不是无缝动画。
掘金安东尼
2022/09/22
5520
每天10个前端小知识 【Day 16】
改变transform或opacity不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。
程序媛夏天
2024/01/18
2510
每天10个前端小知识 【Day 16】
使用CSS3实现60FPS的移动端动画(转)
如果您按照我们的提示,您在移动应用程序中使用动画元素会很容易,在其中适当地使用动画元素也会很容易...
山河木马
2019/03/05
2K0
使用CSS3实现60FPS的移动端动画(转)
干货 | 携程火车票7个优化动画性能的方法
携程火车票营销页使用 css 制作动画很多年了,这大大提高了动画给予页面丰富的视觉体验。不过,在开发的过程中,也遇到了一些性能相关问题和用户反馈,比如头部动画卡顿、页面打开时间较长、页面打开后部分数据加载时间较长等问题。为解决这些问题,我们借助性能检测工具定位问题,并查阅源码、文档等资源解决问题,形成了这篇文章。
携程技术
2023/09/06
3770
干货 | 携程火车票7个优化动画性能的方法
推荐阅读
相关推荐
✍️浏览器渲染原理深度拆解:为什么你的动画总是卡顿?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档