CSS3动画干扰性能优化的完美解决方案
为什么卡住了?
必须提到的是,前端开发人员知道浏览器运行在一个线程上。但是我们应该定义以下几个概念:单线程、主线程和合成线程。虽然说浏览器是单线程执行js的(注意,是执行,不是说浏览器只有一个线程,而是runing),但实际上浏览器有两个重要的执行线程,共同作用渲染一个网页:主线程和合成线程。正常情况下,主线程负责:运行JavaScript;计算HTML元素的CSS样式;页面的布局;将元素绘制到一个或多个位图中;将这些位图交给合成线程。相应地,合成线程负责:通过GPU在屏幕上绘制位图;通知主线程更新页面中可见或即将可见部分的位图;计算页面的哪个部分可见;计算滚动页面时哪个部分将变得可见;滚动页面时,将相应的元素移动到可见区域。
那么,动画为什么会堵塞呢?
原因是主线程和合成线程的调度不合理。下面我们来详细说说日程安排不合理的原因:
当高度、宽度、边距和填充用作过渡值时,浏览器主线程的工作量很大。例如,当从左边距:-20px渲染到左边距-:0时,主线程需要计算样式左边距-3360-19px。Margin-left:-18px,一直到margin-left:0,每次主线程计算风格,合成过程都需要画到GPU上,然后在屏幕上渲染,总共20次主线程渲染,20次合成线程渲染,20次和20次,总共40次计算。
主线程的渲染过程请参考浏览器渲染网页的过程:
使用HTML创建文档对象模型使用CSS执行基于DOM和CSSOM的脚本合并DOM和CSSOM以形成渲染树使用渲染树布局所有元素绘制所有元素
也就是说,主线程每次都需要执行脚本、渲染树、布局和绘制的计算。
如果使用transform,例如translate(-20px,0)来转换transform:translate(0,0),那么主线程只需要执行transform: translate (-20px,0)来转换transform:translate(0,0)一次,然后合成线程转到-
有人可能会说这才提升了19倍,那还有什么提升性能的呢?假设一次10毫秒。那么减少了大约190毫秒的时间消耗。有人会说辣子鸡才190ms,没关系。左边距从-200px到0,一次10ms,10ms*1992s怎么办?有人会说辣子鸡只有2s,所以无所谓。你忘了单线吗?如果网页有三个动画,3*2s=6s,就是6s的性能提升。由于数据是推测性的,暂时不考虑其真实性
为了增强这篇文章的说服力,我将用一个例子来证明我的观点。让我们一起来看看吧
在前端,利用动画实现了H5页面首页的动画过渡,这是一个非常简单的效果。首页加载一个客服头像,先放大,停留700 ms后缩小到顶部.代码如下:
!DOCTYPE html html head lang=' zh-cn ' meta charset=' utf-8 ' meta name=' viewport ' content=' width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scale=1 '脚本类型=' text/JavaScript ' src=' http :http://apps。bdimg。com/libs/jquery/2。1 .1/jquery。量滴js /脚本标题首页加载动画/title头部样式欢迎-主{显示:无;填充-底部: 40px} .top-info { width : 100%;绝对位置:左: 0;top: 93px}。WEC-img {宽度: 175像素;高度: 175像素;相对位置:padding: 23px盒子尺寸:边框盒子;margin: 0 auto}。{内容: }之前的WEC-img :绝对位置:左: 0;top : 0;宽度: 100%;高度: 100%;背景: url(' ./images/KF-欢迎-加载。png ');背景尺寸: 100%;} .wec-img .img-con {宽度: 100%;高度: 100%;边界半径: 50%;/*箱式:边框-盒子;*/background: url(' ./images/KF _ 1。jpg’);背景尺寸: 100%;padding: 1px }。wec-img .img-con img { width : 100%;高度: 100%;边界半径: 50%;} .满载而归WEC-img {-WebKit-transform-origin :中心顶;} .装货。欢迎-主{显示:块;} .装货WEC-img {-网络工具包-动画:淡入。3s轻松实现两者;} .装货WEC-img :之前{-网络套件-动画:旋转。6s。2s线性两者;} .满载而归top-info {-web kit-animate :主填充1s 0s轻松两者;} .满载而归WEC-img {-网络工具包-动画: imgsmall 1s 0s轻松兼顾;} @-网络工具包-关键帧主填充{ 0% {-web套件-transform : translatey(0)} 100% {-web套件-transform : translatey(-87px)} @-web套件-关键帧imgSmall { 0% { width : 175 px;高度: 175像素;padd : 23px } 100% { width : 60px;高度: 60pxpadd : 0;} } @-网络工具包-关键帧FADEIN { 0% { opa city 33600;-web套件-transform :秤(。3)} 100% { opa city 33601;-网络套件-transform :秤(1)} @-网络套件-关键帧旋转{ 0% { opa city 33600;-web工具包-transform :旋转(0度);} 50% { opa city 33601;-网络套件-transform :旋转(180度);} 100% { opa city 33600;-web工具包-变换:旋转(360度);} }/style body div class=' welcome-main ' div class=' top-info ' div class=' WEC-img ' p class=' img-con ' img src=' http : ' alt=' '/p/div/div脚本$().欢迎-主')。添加CLaSS(' loading ');setTimeout(函数(){ $()。你好。).removeClass("加载");$('.欢迎-主')。addClass(')已加载');},700);/脚本/正文/html在铬上测试好吧,但在提测给质量保证的时候发现部分机型,如华为(系统4.2)、oppo(系统5.1)的出现卡顿情况。
百思不得其解,后来参考文章深入浏览器理解半铸钢钢性铸铁(Cast Semi-Steel)动画和过渡的性能问题一文,将图片缩放中动画元素改成变换,如下
@-网络工具包-imgSmall关键帧{ 0% {-web kit-transform : scale(1);} 100% {-WebKit-transform :比例尺(。465);}}果然啊,卡顿问题解决了。
本文深入了解了浏览器中CSS动画和过渡的性能问题。现代浏览器通常有两个重要的执行线程,它们协同工作来呈现网页:主线程和合成线程。
正常情况下,主线程负责:运行JavaScript;计算HTML元素的CSS样式;页面的布局;将元素绘制到一个或多个位图中;将这些位图交给合成线程。
相应地,合成线程负责:通过GPU在屏幕上绘制位图;通知主线程更新页面中可见或即将可见部分的位图;计算页面的哪个部分可见;计算滚动页面时哪个部分将变得可见;滚动页面时,将相应的元素移动到可见区域。
假设我们希望元素的高度从100 px变为200 px,如下所示:
div { height: 100px高度1s线性过渡:} div : hover { height : 200 px;}主线程和合成线程将按照以下流程图执行相应的操作。请注意,橙色框中的操作可能很耗时,而蓝色框中的操作相对较快。
它是使用transform:scale实现的
div { transform:刻度(0.5);transition:变换1s线性;} div : hover { transform : scale(1.0);}此时,流程如下:
也就是说,有了transform,浏览器只需要生成这个元素的位图一次,在动画开始的时候提交给GPU进行处理。之后,浏览器不需要做任何布局、绘制和提交位图。因此,浏览器可以充分利用GPU的特殊功能,快速绘制不同位置的位图,并进行旋转或缩放处理。
为了在数量级上证明这个理论,我打开chrome的时间轴查看FPS页面
其中,以高度作为动画元素时,切换过程中的FPS仅为44。我们知道每秒60帧是最适合人眼的交互方式。如果小于60,人眼可以明显感觉到,这就是为什么会卡住。
渲染和绘制时间如下:
让我们看一下使用transform:scale
FPS达到66,渲染和绘画时间减少3倍。
到目前为止,问题已经解决了。过了几天,看到一个解决Chrome动画“卡壳”的方案,发现打开硬件加速可以优化动画,于是又尝试了一次。
web kit-transform : translate 3d(0,0,0);-moz-transform : translate 3d(0,0,0);-ms-transform : translate 3d(0,0,0);-o-transform: translate3d(0,0,0);transform: translate3d(0,0,0);惊人的事情发生了,FPS达到了72:
总结CSS3动画卡壳的解决方案
1.尽量使用transform作为动画熟悉度,避免使用高度、宽度、边距、填充等。2.要求高的时候可以打开浏览器启动GPU硬件加速。
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。谢谢你的支持。如果你想了解更多,请查看下面的相关链接
版权声明:CSS3动画干扰性能优化的完美解决方案是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。