前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >css3 animation && filter: blur()引发的动画性能问题排查

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

作者头像
2014v
发布2020-04-08 16:05:32
2.3K0
发布2020-04-08 16:05:32
举报
文章被收录于专栏:2014前端笔记

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

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

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

代码语言:javascript
复制
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
截屏2020-03-30 下午9 07 06

因此这个按钮图层再触发repaint操作的时候是只会更新自己,不会影响我们的背景图片。 但是为什么开启了硬件加速的动画,会卡顿呢?

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

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

代码语言:javascript
复制
endCardLayout.isHardwareAccelerated();

发现返回居然是false,

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

代码语言:javascript
复制
getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

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

代码语言:javascript
复制
    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 显示潜在的滚动瓶颈
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 那么浏览器filter是怎么实现的呢,为什么会造成这个卡顿呢?
  • chrome devtool
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档