7

使用CSS3开启GPU硬件加速提升网站动画渲染性能

 3 years ago
source link: https://blogread.cn/it/article/6801?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

  最近几周一直在搞自己的个人网站,一来是为了总结一下近几年自己的前端职业历程,二来是希望把这个网站做成自己的Web版个人履历/简历。网站首屏会有一个跟随鼠标进行空间透视移动的DOM动画效果,这里用到了一些JS逻辑,由于涉及到动画和性能问题,这里简要总结一下开发过程中遇到的一些问题。想来博客已经近两年没有更新过了,甚感愧疚,2014年一定一定一定会勤快些的!

个人网站Demo预览

  大家看过网站之后,应该能大致了解到,动画中使用了很多大尺寸半透明PNG24图片,具体尺寸取决于你电脑的分辨率,目前会根据1920/1440/1024这三种分辨率宽度加载不同尺寸的图片。动画逻辑是每个图片都会以不同的速度跟随鼠标移动,以达到空间感很强的透视效果。具体的js逻辑我会在以后单独写一篇讲解,还会把这个动画写成jQuery插件提供给大家下载,敬请关注^_^

先来说说遇到的问题:

  网站本身设计初衷就没有打算支持IE8及以下版本浏览器,并不是因为代码兼容性问题,而是真的不想迁就那些懒得更新自己操作系统和浏览器的用户,毕竟是我自己的网站,所以我说了算!哈哈~

  没有了低版本IE6浏览器,就不用顾虑他们的性能问题了,本以为开发会一帆风顺,结果”性能问题”竟然出现在了一直以性能出色著称的Chrome浏览器中。

  Chrome下的动画比IE9和FF都要慢很多,一开始觉得是自己的js逻辑问题,因为要遍历9个元素并计算他们的坐标。后来尝试了使用requestAnimationFramewebWorkercanvas,但情况仍然没有任何好转。通过chrome的DevTool中TimeLine监控,发现动画的代码逻辑并没有占用太多资源,反倒是painting消耗了大量的时间,平均才30fps左右。

上图可见主要时间都浪费在painting上了,元素背景图过大导致。

  上面这几张图都是开启GPU硬件加速之前使用Chrome DevTool Timeline功能中Frames模块监测到的数据,明显看到平均帧速率在30fps左右

  其实,chrome对于渲染多张大尺寸图片方面一直表现疲软,之前在开发人人小站瀑布流布局模板的时候就遇到过这类问题,chrome中只要存在大量缩放图片,页面滚动的时候就会极其卡顿,就像是用一台2004年的电脑访问一个2014年的网站一样。chrome对于渲染很多大尺寸图片(尤其是alphy透明度PNG24图片)方面有先天的不足,从它版本10+的时候就有开发者在官方平台报过这个Bug,如今chrome已经更新至版本30+,却依旧没有完美解决这个顽疾。

解决Chrome动画”卡顿”的办法

  为动画DOM元素添加CSS3样式-webkit-transform:transition3d(0,0,0)-webkit-transform:translateZ(0);,这两个属性都会开启GPU硬件加速模式,从而让浏览器在渲染动画时从CPU转向GPU,其实说白了这是一个小伎俩,也可以算是一个Hack,-webkit-transform:transition3d-webkit-transform:translateZ其实是为了渲染3D样式,但我们设置值为0后,并没有真正使用3D效果,但浏览器却因此开启了GPU硬件加速模式。

  这种GPU硬件加速在当今PC机及移动设备上都已普及,在移动端的性能提升是相当显著地,所以建议大家在做动画时可以尝试一下开启GPU硬件加速。

当然也可以这样开启所有浏览器的GPU硬件加速:

webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
-o-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);

  使用-webkit-transform:transition3d(0,0,0)开启GPU硬件加速的chrome中渲染动画性能明显顺畅了许多,平均能达到55fps左右。无图无真相:

开启GPU硬件加速前后帧速率对比图(点击查看清晰大图)

chrome诡异的Bug

  对所有动画DOM元素添加-webkit-transform:transition3d(0,0,0)开启GPU硬件加速之后,又出现了一个chrome诡异的Bug,当你有多个position:absolute;元素添加-webkit-transform:transition3d(0,0,0);开启GPU硬件加速之后,会有几个元素凭空消失,调试许久无果遂Google之,国内暂时没有人发表过关于这类问题的文章,于是在国外网站找呀找,找到了很多与我遇到同样问题的人,但都没有真正靠谱的解决办法,这可能是跟添加-webkit-transform之后chrome尝试使用GPU硬件加速有关系,最后还是要等待Chrome官方更新解决了,当前Chrome版本是33。如果谁发现比较好的解决办法,欢迎提出^_^

其他人遇到的类似问题:
3D CSS transform: translateZ causes elements to disappear in Chrome
Fixed attachment background image flicker/disappear in chrome when coupled with a css transform

如何避免这个问题:

  在使用-webkit-transform尝试对很多DOM元素编写3D动画时,尽量不要对这些元素及他们的父元素使用position:absolute/fixed。(其实这种情况很难避免)
所以我的临时解决办法是,减少使用-webkit-transform:transition3d(0,0,0)的DOM元素数量,从9个减至6个便没有元素消失的现象了。
PS:由于测试环境有限,如果大家发现在你的浏览器还有这个Bug,麻烦留言告诉我,万分感谢!

开启GPU硬件加速可能触发的问题:

通过-webkit-transform:transition3d/translateZ开启GPU硬件加速之后,有些时候可能会导致浏览器频繁闪烁或抖动,可以尝试以下办法解决之:

-webkit-backface-visibility:hidden;
-webkit-perspective:1000;

如何监测动画帧速率

推荐两种实时监测网页渲染帧速率的方法:

1.Chrome的DevTool中TimeLine的Frame模块

2.地址栏输入”chrome:flags”搜索”fps”,将”FPS计数器”开启,浏览器重启后右上角会实时显示帧速率。

我会再过些天单独写一篇关于通过Frame模块监测网站性能的教程,敬请留意^_^

通过-webkit-transform:transition3d/translateZ开启GPU硬件加速的适用范围:

  • 使用很多大尺寸图片(尤其是PNG24图)进行动画的页面。

  • 页面有很多大尺寸图片并且进行了css缩放处理,页面可以滚动时。

  • 使用background-size:cover设置大尺寸背景图,并且页面可以滚动时。(详见:https://coderwall.com/p/j5udlw)

  • 编写大量DOM元素进行CSS3动画时(transition/transform/keyframes/absTop&Left)

  • 使用很多PNG图片拼接成CSS Sprite时

我能想到的暂时只有这五种情况,欢迎大家补充。

  通过开启GPU硬件加速虽然可以提升动画渲染性能或解决一些棘手问题,但使用仍需谨慎,使用前一定要进行严谨的测试,否则它反而会大量占用浏览网页用户的系统资源,尤其是在移动端,肆无忌惮的开启GPU硬件加速会导致大量消耗设备电量,降低电池寿命等问题。

觉得文章有用?立即:

和朋友一起 共学习 共进步!

建议继续学习:

QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK