【前端优化之渲染优化】大屏android手机动画丢帧的背后 - 叶小钗

标签: 前端 优化 渲染 | 发表时间:2015-03-05 18:31 | 作者:叶小钗
出处:

前言

上周我与阿里的宇果有一次技术的交流,然后对天猫H5站点做了一些浅层次的分析,后面点时间基本天天都会有联系,中途聊了一些技术细节、聊了双方团队在干什么,最后聊到了前端优化。因为我本身参与了几次携程H5站点的优化,在这方面有一些心得,但是与宇果交流的过程中发现我们在优化的时候忽略了一些细节。

携程做优化的时候整个重心基本放到了尺寸的缩减,和宇果的交流过程中他提出了渲染优化,其实渲染优化无非是减少回流,对于减少回流我们也有一些概念,我一直认为这个事情应该业务开发关注而不是框架关注(事实上框架也无法关注),所以对一些BUG采取了表现层面的解决,却对真相视而不见的做法,现在想来真的有点无知,这里便以一个原来的渲染BUG为切入点,将最近与宇果的交流所得整理下。

宇果博客: http://www.ghugo.com/

回流与重绘

首先,我们再次复习一下回流与重绘的知识,浏览器会解析三个东西:HTML、Javascript、CSS。

浏览器首先会根据HTML生成DOM Tree,其次会根据CSS生成CSS Rule Tree,javascript可以通过DOM API与CSS API操作DOM Tree与CSS Rule Tree,从而引起页面变化。

浏览器解析结束会通过DOM Tree与CSS Rule Tree形成render tree,只有display不为none的元素才会形成render Tree,render Tree形成后浏览器会调用GUI绘制页面,在此之前做的一件事情便是layout或者说reflow。上面的描述简单而言可以分为以下流程:

l  生成DOM树

l  计算CSS样式

l  构建render tree

l  reflow,定位元素位置大小

l  绘制页面

在这个过程中,若是javascript动态改变DOM Tree便会引起reflow

页面中的元素改变,只要不影响尺寸,比如只是颜色改变只会引起repaint不会引起回流

否则,reflow不可避免,这个时候便需要重新计算形成render Tree

reflow分为局部回流与全局回流,会影响下面的,不会影响上面的元素

reflow耗用的系统资源较大,DOM Tree中受到影响的节点皆会reflow,然后影响其子节点最坏的情况是所有节点reflow,该问题引发的现象便是低性能的电脑风扇不停的转,手机变得很热,并且非常耗电,以下操作可能引起reflow

l  操作dom结构

l  动画

l  DOM样式修改

l  获取元素尺寸的API

android大屏手机渲染BUG

这个是我们一个tab组件,这个组件按道理说非常简单:

1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
5 <title></title>
6 <style type="text/css">
7 body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
8
9 ul, ol { list-style: none; margin: 0; padding: 0; }
10
11 .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
12
13 .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
14
15 .cui-tab-mod li.cui-tab-current { color: #099fde; }
16
17 .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease-in-out; -moz-transition: -moz-transform 300ms ease-in-out; -ms-transition: -ms-transform 300ms ease-in-out; transition: transform 300ms ease-in-out; z-index: -1; }
18
19 .cui-tabnum2 { width: 50%; }
20
21 .cui-tabnum3 { width: 33.33333%; }
22
23 .cui-tabnum4 { width: 25%; }
24
25 .cui-tabnum5 { width: 20%; }
26
27 .cui-tabnum6 { width: 16.66666%; }
28
29 .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
30
31 .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }
32
33 .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
34
35 .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); }
36
37 .cui-tab-mod li:nth-of-type(4).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(300%,0,0); -moz-transform: translate3d(300%,0,0); -ms-transform: translate3d(300%,0,0); transform: translate3d(300%,0,0); }
38
39 .cui-tab-mod li:nth-of-type(5).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(400%,0,0); -moz-transform: translate3d(400%,0,0); -ms-transform: translate3d(400%,0,0); transform: translate3d(400%,0,0); }
40
41 .cui-tab-mod li:nth-of-type(6).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(500%,0,0); -moz-transform: translate3d(500%,0,0); -ms-transform: translate3d(500%,0,0); transform: translate3d(500%,0,0); }
42 </style>
43 <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
44 </head>
45 <body>
46
47 <ul class="cui-tab-mod">
48 <li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
49 <li data-key="1" data-index="1" class="cui-item">美国</li>
50 <li data-key="2" data-index="2" class="cui-item">日本</li>
51 <i class="cui-tab-scrollbar cui-tabnum3"></i>
52 </ul>
53 <script type="text/javascript">
54 $(function () {
55 var wrapper = $('.cui-tab-mod');
56 wrapper.on('click', function (e) {
57 var el = $(e.target);
58 if (el.hasClass('cui-item')) {
59 wrapper.find('li').removeClass('cui-tab-current');
60 el.addClass('cui-tab-current');
61 }
62 });
63 });
64 </script>
65 </body>
66 </html>

点击一下就让当前item获取class,然后文字样式会改变,下面一个横线也会动画滑动过去,但是这个东西在android大屏手机上却出了问题(比如note2),他会这样表现:

如图所示,class过去了,文字颜色也变了,但是下面对应的竖条却没有过去,我当时一看就知道是渲染的问题并且马上给出了一个解决方案:

1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
5 <title></title>
6 <style type="text/css">
7 body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
8
9 ul, ol { list-style: none; margin: 0; padding: 0; }
10
11 .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
12
13 .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
14
15 .cui-tab-mod li.cui-tab-current { color: #099fde; }
16
17 .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease-in-out; -moz-transition: -moz-transform 300ms ease-in-out; -ms-transition: -ms-transform 300ms ease-in-out; transition: transform 300ms ease-in-out; z-index: -1; }
18
19 .cui-tabnum2 { width: 50%; }
20
21 .cui-tabnum3 { width: 33.33333%; }
22
23 .cui-tabnum4 { width: 25%; }
24
25 .cui-tabnum5 { width: 20%; }
26
27 .cui-tabnum6 { width: 16.66666%; }
28
29 .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
30
31 .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }
32
33 .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
34
35 .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); }
36
37 .cui-tab-mod li:nth-of-type(4).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(300%,0,0); -moz-transform: translate3d(300%,0,0); -ms-transform: translate3d(300%,0,0); transform: translate3d(300%,0,0); }
38
39 .cui-tab-mod li:nth-of-type(5).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(400%,0,0); -moz-transform: translate3d(400%,0,0); -ms-transform: translate3d(400%,0,0); transform: translate3d(400%,0,0); }
40
41 .cui-tab-mod li:nth-of-type(6).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(500%,0,0); -moz-transform: translate3d(500%,0,0); -ms-transform: translate3d(500%,0,0); transform: translate3d(500%,0,0); }
42 </style>
43 <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
44 </head>
45 <body>
46
47 <ul class="cui-tab-mod">
48 <li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
49 <li data-key="1" data-index="1" class="cui-item">美国</li>
50 <li data-key="2" data-index="2" class="cui-item">日本</li>
51 <i class="cui-tab-scrollbar cui-tabnum3"></i>
52 </ul>
53 <script type="text/javascript">
54 $(function () {
55 var wrapper = $('.cui-tab-mod');
56 wrapper.on('click', function (e) {
57 var el = $(e.target);
58 var toolBar = $('.cui-tab-scrollbar');
59 if (el.hasClass('cui-item')) {
60 wrapper.find('li').removeClass('cui-tab-current');
61 el.addClass('cui-tab-current');
62 setTimeout(function () {
63 toolBar.width('width', toolBar.width());
64 }, 0)
65 }
66 });
67 });
68 </script>
69 </body>
70 </html>

这里设置下划线width的时候触发了其回流,而setTimeout会在主程序执行结束后才触发,于是BUG修复了,核心代码如下:

1 $(function () {
2 var wrapper = $('.cui-tab-mod');
3 wrapper.on('click', function (e) {
4 var el = $(e.target);
5 var toolBar = $('.cui-tab-scrollbar');
6 if (el.hasClass('cui-item')) {
7 wrapper.find('li').removeClass('cui-tab-current');
8 el.addClass('cui-tab-current');
9 //修复丢帧问题
10 setTimeout(function () {
11 toolBar.width('width', toolBar.width());
12 }, 0)
13 }
14 });
15 });

这个BUG解决后也没有再关注,时序纷飞,一年过去了却和宇果聊天过程中再次响起这个问题,才响起自己忽略的是什么。

重新认识Timeline

我们常常有一个问题,如何知道页面哪里的渲染有问题,如何捕捉?

如果没有一个实际可用的工具的话,我们只能由外文或者博客获取这类知识,这个时候就和我解决上述问题差不多了,仅仅从皮毛上知道是渲染导致的问题,并且能使用回流解决问题,却是对渲染性能造成负担,所以如何捕捉渲染问题衡量渲染性能这个是第一位,好在chrome提供了Timeline:

以我们的页面为例,我们开始监控,这里稍微改变一下代码:

1 var wrapper = $('.cui-tab-mod');
2 wrapper.on('click', function (e) {
3 var el = $(e.target);
4 var toolBar = $('.cui-tab-scrollbar');
5 if (el.hasClass('cui-item')) {
6 wrapper.find('li').removeClass('cui-tab-current');
7 el.addClass('cui-tab-current');
8 // setTimeout(function () {
9 // toolBar.width('width', toolBar.width());
10 // }, 0)
11 }
12 });
13
14 function setIndex(i) {
15 var els = wrapper.find('li');
16 els.removeClass('cui-tab-current');
17 els.eq(i).addClass('cui-tab-current');
18 }

我首先点击开始监控,然后鼠标不在页面做任何操作,在控制台输入一句:

setIndex(1)

于是页面会发生改变,这个时候,我们得到的图是:

这张图其实最初我也是看热闹的,昨天根据宇果的指点,才稍微看出点门道了:

首先请看上图中的一个个透明框,每个透明框便是两次显示器刷新周期中等待的时间,其中有一个非常关键的单位叫做fps,这个60fps是个什么东西呢?

60fps与16ms

所谓60fps便是说屏幕1s会刷新60次,意思是大概16.5ms屏幕会刷新一次,在这一次刷新中浏览器会干很多事情,这里还是以图示为例,这里有2个前提:

① 我们鼠标并未操作

② 我们页面很单一

所以在我们执行setIndex前,浏览器根本没有任何消耗,每一次的刷新干了这几件事情:

刚刚整个过程一过经过了2.29秒,浏览器发生了这些事情:

从白条来看,浏览器处理整个动作大概花费320ms,这里出了4种颜色,这个也比较关键。

4种颜色

黄色是说明正在执行javascript脚本,从这里可以看出,js执行的速度是非常快的,这里包含了设值class、移除class,获取width等一系列操作,浏览器会等一次结束后才发生渲染。

紫色是说明正在回流,也就是我们传说中的渲染,这个是非常耗费性能的,我们这里具体跟进去看看:

接下来触发了css3过渡transition的动画,下面的滚动条开始了不停的移动:

可以看到,后续所有的运动只影响了一个元素,这个元素便是滚动条,这里为了验证刚刚所说,我们做两个事情:

① 使用click触发索引更改

② 为下划线添加子元素

这里有个非常不同的就是,我鼠标在界面操作了,不可避免的会引起一些move样式改变,所以有重绘有回流,都比较轻,比较关键的是,其中多了一个click操作(Event),但是下面动画时候影响的元素仍然只是一个,这个有点不明原因,我这里特别将transform改成了left,因为transform更加平滑,我想找出原因,却发现了另一个现象:

可以看出transformd导致的动画只会执行一次paint,便是最初那一次,而使用left的话却在不停的paint,这个是资源消耗的对不:

可以看出,使用left时候出现了锯齿状,这个时候我们可以得出一个结论,transform的移动确实比left节省性能。

至此我们对chrome的Timeline有了一个新的认识,但是我们这里的观察全部是在PC端发生的,而手机端是怎么样的呢?

移动端的渲染

这个图与上图形成了鲜明对比,PC端就只有很小的波动,手机端却引起了很多涟漪,导致这个问题的原因是硬件设施(这里是盗图):

PS:这里苦于没有Android设备,chrome电脑又暂时抽风不能真机调试,便去同事那里草草截图,哎......

丢帧的发生

如前所述,浏览器一次的刷新约16ms,以一次原子行为来说是这样的:

脚本运行时间+渲染时间+绘制时间<16ms

如果中间有一次的操作比如渲染的时间大于了16ms而导致浏览器没有来得及绘制,那么那次的操作便失效了,这个就是所谓的丢帧。

我们在note2上运行程序时会导致丢帧,应该就是其中一次超出了时限,因为class变化会引起样式重新计算,但是只是文字变化的话只是会引起重绘,所以主要问题发生在transition动画。

而我们的解决方案是setTimeout,这个造成的影响是:

我们发现了,就算没有动画,重新计算样式那里导致的回流以及十分严重,是他挤掉了后续的操作吗,他重新计算样式中的因素有很多,我怀疑的目光却放到了这段css:

.cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }

测试下来,确实与他相关:

1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
5 <title></title>
6 <style type="text/css">
7 body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
8 ul, ol { list-style: none; margin: 0; padding: 0; }
9 .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
10 .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
11 .cui-tab-mod li.cui-tab-current { color: #099fde; }
12 .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease ; transition: transform 300ms ease ; z-index: -1; -webkit-backface-visibility:hidden; backface-visibility:hidden; }
13 .cui-tabnum2 { width: 50%; }
14 .cui-tabnum3 { width: 33.33333%; }
15 .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
16 </style>
17 <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
18 </head>
19 <body>
20 <ul class="cui-tab-mod">
21 <li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
22 <li data-key="1" data-index="1" class="cui-item">美国</li>
23 <li data-key="2" data-index="2" class="cui-item">日本</li>
24 <i class="cui-tab-scrollbar cui-tabnum3"><span>1</span></i>
25 </ul>
26 <script type="text/javascript">
27 var wrapper = $('.cui-tab-mod');
28 var toolBar = $('.cui-tab-scrollbar');
29 var els = wrapper.find('li');
30 wrapper.on('click', function (e) {
31 toolBar.css({
32 '-webkit-transform': 'translate3d(100%,0,0)',
33 'transform': 'translate3d(100%,0,0)'
34 })
35 var el = $(e.target);
36 });
37 </script>
38 </body>
39 </html>

如果这样,我直接操作toolBar便可以绕过该BUG,但是我还是不太确定,所以有了这段代码:

1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
5 <title></title>
6 <style type="text/css">
7 body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
8
9 ul, ol { list-style: none; margin: 0; padding: 0; }
10
11 .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
12
13 .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
14
15 .cui-tab-mod li.cui-tab-current { color: #099fde; }
16
17 .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease ; transition: transform 300ms ease ; z-index: -1; -webkit-backface-visibility:hidden; backface-visibility:hidden; }
18
19 .cui-tabnum2 { width: 50%; }
20
21 .cui-tabnum3 { width: 33.33333%; }
22
23 .cui-tabnum4 { width: 25%; }
24
25 .cui-tabnum5 { width: 20%; }
26
27 .cui-tabnum6 { width: 16.66666%; }
28
29 .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
30
31 .cui-tab-mod cui-tab-current .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
32
33
34 .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }
35
36 .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); }
37
38 .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); }
39
40 </style>
41 <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
42 </head>
43 <body>
44
45 <ul class="cui-tab-mod">
46 <li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
47 <li data-key="1" data-index="1" class="cui-item">美国</li>
48 <li data-key="2" data-index="2" class="cui-item">日本</li>
49 <i class="cui-tab-scrollbar cui-tabnum3"><span>1</span></i>
50 </ul>
51 <script type="text/javascript">
52 var wrapper = $('.cui-tab-mod');
53 var toolBar = $('.cui-tab-scrollbar');
54 var els = wrapper.find('li');
55
56 wrapper.on('click', function (e) {
57 var el = $(e.target);
58 els.removeClass('cui-tab-current');
59 el.addClass('cui-tab-current');
60 toolBar.css('left', '0');
61
62 // setTimeout(function () {
63 // toolBar.width('width', toolBar.width());
64 // }, 0)
65 });
66
67
68
69 </script>
70 </body>
71 </html>
1 var wrapper = $('.cui-tab-mod');
2 var toolBar = $('.cui-tab-scrollbar');
3 var els = wrapper.find('li');
4
5 wrapper.on('click', function (e) {
6 var el = $(e.target);
7 els.removeClass('cui-tab-current');
8 el.addClass('cui-tab-current');
9 toolBar.css('left', '0');
10
11 // setTimeout(function () {
12 // toolBar.width('width', toolBar.width());
13 // }, 0)
14 });

两次对比没有什么差距,这个BUG导致的原因还需要深究,待我哪天去真机测试...... 

setTimeout动画

另外,最好也不要使用setTimeout之类的定时器来实现动画,下面这个动画操作也是非常消耗的:

这里如果使用requestAnimationFrame便可以避免Timer的影响。

fixed元素

一般来说,fixed元素在手机上尤其卡,我们这里也来追踪一下原因:

可以看到,fixed元素与left一样的都会不断的Paint,所以他卡呢,至于如何避免不同的团队有不同的方案。

结语

今天回顾了与宇果的交流过程中的渲染优化相关,希望对各位有用, 文中有误请您提出,最后微博求粉:


本文链接: 【前端优化之渲染优化】大屏android手机动画丢帧的背后,转载请注明。

相关 [前端 优化 渲染] 推荐:

浅析渲染引擎与前端优化

- - JDC | 京东设计中心
浅析浏览器内核的工作原理(以. 浅析由浏览器内核想到的前端优化,或者说前端优化规则是从哪儿来的. 大家知道,大部分的 WEB 页面依托浏览器呈现,而浏览器能够将页面展示出来,基本依赖于浏览器的内核,即渲染引擎. 今天以 Chrome 浏览器的内核 WebKit(更确切是 WebKit 分支 Blink,以下统称为 WebKit )为例,对渲染引擎如何展示页面做个简单、全面的了解.

前端首屏渲染时间的极致优化

- - SegmentFault 最新的文章
我们知道,用户体验是 Web 产品最为重要的部分. 尽可能减少首屏加载时间,更为流畅地展示用户所需求的内容,会是用户是否留存的关键因素. 而随着现代 Web 业务可供用户的交互行为越来越多,前端项目的复杂度越来越高,每个页面的渲染时间也必然越来越长,这就导致了用户的体验不佳,用户的操作变慢. 为此,前端工程师们在首屏请求的各个阶段中持续钻研,不断探究如何将首次页面渲染的时间减少到更小,力求提供更为优秀的产品体验.

【前端优化之渲染优化】大屏android手机动画丢帧的背后 - 叶小钗

- - 博客园_首页
上周我与阿里的宇果有一次技术的交流,然后对天猫H5站点做了一些浅层次的分析,后面点时间基本天天都会有联系,中途聊了一些技术细节、聊了双方团队在干什么,最后聊到了前端优化. 因为我本身参与了几次携程H5站点的优化,在这方面有一些心得,但是与宇果交流的过程中发现我们在优化的时候忽略了一些细节. 携程做优化的时候整个重心基本放到了尺寸的缩减,和宇果的交流过程中他提出了渲染优化,其实渲染优化无非是减少回流,对于减少回流我们也有一些概念,我一直认为这个事情应该业务开发关注而不是框架关注(事实上框架也无法关注),所以对一些BUG采取了表现层面的解决,却对真相视而不见的做法,现在想来真的有点无知,这里便以一个原来的渲染BUG为切入点,将最近与宇果的交流所得整理下.

Android性能优化之渲染篇

- - 移动开发 - ITeye博客
关注微信号:javalearns   随时随地学Java. Google近期在Udacity上发布了Android性能优化的在线课程,分别从渲染,运算与内存,电量几个方面介绍了如何去优化性能,这些课程是Google之前在Youtube上发布的Android性能优化典范专题课程的细化与补充. 下面是渲染篇章的学习笔记,部分内容和前面的性能优化典范有重合,欢迎大家一起学习交流.

从零开始写一个微前端框架(渲染篇)

- - IT瘾-dev
自从微前端框架 micro-app开源后,很多小伙伴都非常感兴趣,问我是如何实现的,但这并不是几句话可以说明白的. 为了讲清楚其中的原理,我会从零开始实现一个简易的微前端框架,它的核心功能包括:渲染、JS沙箱、样式隔离、数据通信. 由于内容太多,会根据功能分成四篇文章进行讲解,这是系列文章的第一篇:渲染篇.

Web前端优化

- - JavaScript - Web前端 - ITeye博客
优点:直接使用浏览器内存的缓存数据,减少网站后台压力,用户体验(速度)好. 缺点:对于时时变化的动态页面,这种情况就不能容忍了,因为每次访问的都是第一次访问的内容,这样即使所请求的页面已经变化了,用户也不可能知道,所以此场景必须要消除这种缓存的影响. 延迟加载,将资源延迟到需要的时候的加载,例如detail页面,相关产品推荐,当用户浏览更多的信息往下拉动滚动时,才进行加载,异步加载可以大幅减少对后端资源的使用,在需要的时候加载,是资源合理使用常用的方式,但是也带来一个问题,当往下拉才去加载,如果性能不够好,用户的体验其实是不好的,“菊花”转动的时间会比较长,同时异步加载对前端性能的作用也是非常明显的,渲染的节点数量大幅减少.

前端性能优化

- - JavaScript - Web前端 - ITeye博客
  在浏览器(客户端)和服务器发生通信时,就已经消耗了大量的时间,尤其是在网络情况比较糟糕的时候,这个问题尤其的突出.   一个正常HTTP请求的流程简述:如在浏览器中输入" www.xxxxxx.com"并按下回车,浏览器再与这个URL指向的服务器建立连接,然后浏览器才能向服务器发送请求信息,服务器在接受到请求的信息后再返回相应的信息,浏览器接收到来自服务器的应答信息后,对这些数据解释执行.

Web前端优化最佳实践

- Jimmy - 中文热文榜|最新
还有 Jason, Bixuan, 曦, 推荐,查看全部 8 个推荐. 博评 - Sting的网经发表于2010-08-08 08:41:10. Google的前端优化最佳实践 Yahoo的前端优化最佳实践. Web前端优化最佳实践之Content篇. 尽量减少 HTTP 请求 (Make Fewer HTTP Requests).

前端开发中的HTML优化

- - 可咔酷 | 网络杂货铺
在前端领域中,对Javascript和CSS的优化一直是大家关注的焦点,相应的压缩优化工具也非常丰富,相对而言对HTML优化的关注则显得有些冷淡. 在 Steve Souders的大作《Even Faster Web Sites》中谈到非常多有效的前端优化方法,例如Javascript的加载、CSS选择符、图片优化、gzip、iframe问题等,唯独没有细说HTML优化.

mod_pagespeed:傻瓜式前端优化

- - 知道分子
曾经有位朋友自己做了个小网站,刚开始没什么人气,后来不小心把流量搞大了,用户抱怨访问缓慢,就让我帮忙看看哪里可以优化. 那时 Steve Souders 老师的 YSlow 14条军规刚刚新鲜出炉,开宗明义第一句便是:网页性能 80% 消耗在前端. 于是运用 Firefox+Firebug+YSlow 工具,轻松找到那些大图小用、过期时间太短、JS/CSS位置不正确、没有精简压缩的罪恶之源.