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

GPU硬件加速

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

彬Go的个人网站
个人网站Demo预览

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

先来说说遇到的问题:

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

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

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

chrome_timeline_frames_30fps chrome_timeline_frames_30fps

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

chrome_timeline_frames_30fps
chrome_timeline_frames_30fps

  上面这几张图都是开启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左右。无图无真相:

chrome_timeline_frames_60fps
chrome_timeline_frames_60fps
chrome_timeline_frames_60fps
开启GPU硬件加速前后帧速率对比
开启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模块
chrome_timeline_frames

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

我会再过些天单独写一篇关于通过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硬件加速会导致大量消耗设备电量,降低电池寿命等问题。

您还可以参考以下HTML5相关文章:
人人网首页拖拽上传详解(HTML5 Drag&Drop、FileReader API、formdata)
HTML5 Drag&Drop 拖拽、FileReader实例教程
关于HTML 5 canvas 的基础教程

留意更新

订阅彬Go以查看HTML5最新资源、教程。

转载声明:
原载:彬Go——关注前端开发 & Web UI设计
本文链接:http://blog.bingo929.com/transform-translate3d-translatez-transition-gpu-hardware-acceleration.html如需转载必须以链接形式注明原载或原文地址,谢谢合作

19 Comments

发表评论

  • 世界,您好! – kevin-zwr
    2017-01-18

    […] 《使用CSS3开启GPU硬件加速提升网站动画渲染性能》 《人人网首页拖拽上传详解(HTML5 Drag&Drop、FileReader API、formdata)》 […]

  • 匿名
    2016-11-21

    开启之后华为手机上的列表就不显示了

  • Mr.Song
    2016-11-18

    webkit-transform: translateZ(0);
    -moz-transform: translateZ(0);
    -ms-transform: translateZ(0);
    -o-transform: translateZ(0);
    transform: translateZ(0);
    ———————————————-
    楼主上边这个地方写错了:
    webkit-transform: translateZ(0); 应该是 -webkit-transform: translateZ(0); 你忘记加横线了,希望楼主能看见,及时改正,谢谢

  • Mr.Song
    2016-11-18

    完美解决了我的问题,谢谢楼主,滑动卡顿的问题折磨一周了,今天终于解决了
    ———————————————————
    webkit-transform: translateZ(0);
    -moz-transform: translateZ(0);
    -ms-transform: translateZ(0);
    -o-transform: translateZ(0);
    transform: translateZ(0);

  • 匿名
    2016-08-14

    Just leave a comment

  • 自定义元素–为你的HTML代码定义新元素 | FLY.Lee
    2016-08-05

    […] 《使用CSS3开启GPU硬件加速提升网站动画渲染性能》 《HTML5 WebSockets 基础使用教程》 《关于HTML 5 canvas 的基础教程》 […]

  • https://www.zotero.org/airjordansforsale
    2016-06-02

    Your comment is awaiting moderation.

    i am the first time coming here by google
    https://www.zotero.org/airjordansforsale https://www.zotero.org/airjordansforsale

  • 匿名
    2016-04-26

    在哪里加也没有说清楚,就说了需要什么。。。唉

  • 北辰神Only
    2016-03-24

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

    在哪加呢?加了硬件加速的元素么?

  • asdfe
    2016-03-02

    啊哦 bootstrap?