Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

css3 animation && filter: blur()引发的动画性能问题排查 #24

Open
z2014 opened this issue Mar 30, 2020 · 0 comments
Open

css3 animation && filter: blur()引发的动画性能问题排查 #24

z2014 opened this issue Mar 30, 2020 · 0 comments

Comments

@z2014
Copy link
Owner

z2014 commented Mar 30, 2020

这篇文章记录了自己排查动画问题时的思路,最后的解决有一些侥幸,也是因为最近刚好学习了部分安卓代码,技术视野稍微开阔了些

我们在工作中经常会遇到一些动画卡顿的问题,往往是一些性能比较差的安卓手机,笔者最近就遇到了这样的情况,这里也记录下本次排查问题的过程。

因为页面并不复杂,所以看到页面动画卡顿之后,能够很快速的猜想到是哪些css属性引起的卡顿,通过注释掉代码后,就能够很快的验证自己的推论,这次排查的页面里,导致页面卡顿的是下面这两个属性。

bg-img {
    filter: blur(10px);
}
btn {
    animation: scaleAnimation linear 1.5s 1000 2s;
}
@keyframes scaleAnimation {
    0% {
        transform: scale(1);
    }
    12.5% {
        transform: scale(1.05);
    }
    25% {
        transform: scale(1);
    }
    37.5% {
        transform: scale(1.05);
    }
    50% {
        transform: scale(1);
    }
    62.5% {
        transform: scale(1.3);
    }
    75% {
        transform: scale(1);
    }
    87.5% {
        transform: scale(1.05);
    }
    100% {
        transform: scale(1);
    }
}

一开始猜想可能是在1.5s中,定义不同阶段的动画间隔太短,导致了按钮的卡顿,
但是当我只保留了scaleAnimation中的3个阶段后,发现动画还是能看出来卡顿,
因此应该不是scaleAnimation的问题,同时我又将filter样式注释掉后,发现动画变得流畅了。

那最初的结论就是因为filter样式导致了动画的卡顿。

那么浏览器filter是怎么实现的呢,为什么会造成这个卡顿呢?

后来就搜到了这篇文章,
blur会根据周围像素的值,根据权重计算一个中心点的高斯模糊值,很显然,我们并不是要去优化这个算法,那只能换一个思路:

是否是因为动画,导致每次动画重新渲染时,也引发了背景图片的重绘?
在这个过程中,这篇文章介绍的很清楚,
样式优化会涉及到下面几个环节:
style -> layout -> paint -> composite
一般会有下面3种方式的情况:

  • 1.修改了一个DOM的layout (影响了布局),比如width,height,那么浏览器就会进行reflow(重排),然后再进行重绘。
    1. 修改了页面的"paint only",比如颜色,阴影这种,那么浏览器就会跳过布局,只会绘制和渲染层合并。
  • 3.如果你修改一个非样式且非绘制的CSS属性,那么浏览器完成样式计算之后,会跳过布局和绘制的过程,直接进行渲染层合并。

从我们遇到的问题来看,我们需要优化的是第3种情况,也就是渲染层合并。那么有没有可能是因为我们的背景图片和按钮渲染在了同一渲染层,导致filter每次都要进行重新计算呢?

于是打开chrome的控制台发现,通过translate3d,目前的按钮已经是一个单独的图层了
截屏2020-03-30 下午9 07 06
因此这个按钮图层再触发repaint操作的时候是只会更新自己,不会影响我们的背景图片。
但是为什么开启了硬件加速的动画,会卡顿呢?

目前h5能做的优化内容看起来已经都做了,这个时候难道真的是安卓手机性能太差吗?
于是基本上已经放弃的我想做最后一次验证,就是客户端是否已经开启了硬件加速,因为跑在我们客户端的webview上,我们还是要确认下到底是否开启了硬件加速,不然h5做的这些优化都是白费。

也是最近刚好涉及了一些简单的客户端的开发,很快的在性能差的手机上构建了sdk demo,
再打开webview前加入了这一行代码

endCardLayout.isHardwareAccelerated();

发现返回居然是false,

看到android官网上介绍,下面这部分代码可以开启窗口级别的硬件加速

getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

查看android代码后,确实onBeforeCreate已经开启了硬件加速,
但是看到我们继续定位到webview容器的layout时,发现调用了这么一行代码

    myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

原来客户端专门针对endcard这个view,关闭了硬件加速

so ga!!!!
成功破案

chrome devtool

  • 1、Show paint rectangles 显示绘制矩形
  • 2、Show composited layer borders 显示层的组合边界(注:蓝色的栅格表示的是分块)
  • 3、Show FPS meter 显示 FPS 帧频
  • 4、Enable continuous page repainting 开启持续绘制模式 并 检测页面绘制时间
  • 5、Show potential scroll bottlenecks 显示潜在的滚动瓶颈

参考文章

滚动列表优化
手淘动画优化

@z2014 z2014 changed the title css3 animation filter: blur()引发的性能问题排查 css3 animation && filter: blur()引发的性能问题排查 Mar 30, 2020
@z2014 z2014 changed the title css3 animation && filter: blur()引发的性能问题排查 css3 animation && filter: blur()引发的动画性能问题排查 Mar 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant