为什么transform比较圆滑? CSS3动画粘贴性能优化解决方案
最近一直在开发小程序。和vue一样,它们都有生命周期。
onLoad 监控页面加载 onReady 监控初始页面渲染完成 onShow 监控页面显示
这是什么意思?
所以这又碰到了我的知识盲点,不过尽管有一些绊脚石,项目也差不多完成了,但是我在渲染 CSS3 动画时遇到了性能问题,所以我被迫返回并从渲染网页浏览器。从流程入手,找到动画卡顿的核心。
在浏览器中渲染网页的过程如下:
使用 HTML 创建文档对象模型 (DOM) 使用 CSS 创建 CSS 对象模型 (CSSOM) 基于 DOM 运行脚本 (Scripts) CSSOM 通过合并 DOM 和 CSSOM,创建渲染树(Render Tree) 使用渲染树的布局(Layout)所有元素来渲染(Painting)所有元素
可以将Alon前端性能优化和 Android 开发结合起来页面显示选项。
Android开发者选项页面查看布局
如何判断移动应用是原生、WebView还是混合?简单来说,该应用程序的大部分内容是白色的,没有红线标记,但上面有按钮和图像。等待时,它是一个 webview,即通过伪浏览器请求的数据。网络断开时,打开应用程序时应用程序中不显示任何内容
onLoad 监控页面加载 界面渲染后,即通过。当json中的配置项生成原生界面时,webview部分开始渲染,页面仅被调用一次。 onReady 监听页面初始渲染完成情况 该页面只会被调用一次,表明页面已准备就绪,可以与视图层交互。 onShow 监控页面的显示,并在每次打开页面时调用该函数。
我们的动画应该放在哪里?
应该放在 onShow 中,因为每次打开时我都会看到动画。
为什么会结冰?
有一个前提需要提一下。所有前端开发人员都知道浏览器运行在单线程上。但是,我们需要澄清以下术语:单丝、短纤维和合成纤维。
虽然说浏览器是单线程运行js的(注意,运行并不是说浏览器只有一个线程,而是正在运行),但实际上浏览器有两个重要的执行线程,这2个线程协同工作渲染网页:主线程和创建线程。
一般来说,主线程负责:运行JavaScript;计算 HTML 元素的 CSS 样式;页面布局;将元素绘制到一个或多个位图中;并将这些位图传递给合成线程。
相应地,合成线程负责:通过GPU将位图绘制到屏幕上;通知主线程更新页面中可见或将变得可见的部分的位图;计算页面的哪一部分是可见的;计算页面滚动时哪些部分变得可见;滚动页面时,将元素移动到可见区域的相应位置。
那么为什么动画会卡住呢?
原因是主纤维与合成纤维的布局不相称。
我们来详细说说规划不合理的原因。
使用高度、宽度、边距和填充作为过渡值会导致浏览器主线程的工作负载过重。例如,当从 margin-left: -20px 渲染到 margin-left:0 时,主线程必须计算样式 margin-left:-19px 、 margin-left:-18px 到 margin-left:0 ,并且每次主线程计算样式,合成过程需要在GPU上绘制然后在屏幕上渲染,前后总共20次。次主线程的渲染,20个复合线程渲染,20+20次,共40次计算。
在浏览器中可以看到网页渲染过程中的主线程渲染过程:
使用 HTML 创建文档对象模型(DOM) 使用 CSS 创建 CSS 对象模型(CSSOM) 运行基于 DOM 和 CSSOM 的脚本(scripts)) 合并 DOM 和 CSSOM,创建渲染树(Render Tree) 利用渲染树的布局(Layout)来渲染(Painting)所有元素
也就是说主线程每次都必须运行脚本、渲染树、布局和绘画四个阶段的计算。
而如果使用transform,例如transform:translate(-20px,0)到transform:translate(0,0),主线程只需要对transform做translate:translate(-20px,0):翻译(0)一次,0)然后合成线程立即将-20px转换为0px。在这种情况下,总计算量为1+20。
有人可能会说这个只改进了19次。有什么好的性能提升吗?
假设一次 10 毫秒。
这减少了约190ms的时间消耗。
有人会说,辣子鸡,才190ms,无所谓。
如果左边距一次从-200px到0.10ms怎么办,10ms*199≈2s。
也有人说辣子鸡只有2个,没关系。
你忘记了单线程吗?
如果一个网页有3个动画,3*2s=6s,也就是6s的性能提升。由于这些都是推测,其真实性暂时不予考虑。在本文后面,我对 chrome devtools 性能进行了实验。
要知道,在当今“客户至上”的世界里,良好的用户体验是所有产品都必须遵循的规则。无论是作为开发人员还是产品经理,追求性能最大化是我们创造优秀产品所需要的。基本素质。
也许看完我有些不专业的分析,你对两种性能不同的动画方案的主线程、合成线程及其工作流程还不太了解。大家可以阅读翻译后的博客(英文原版链接已过期):深入理解浏览器中的CSS动画和转场性能问题
这篇文章完美的描述了浏览器主线程和合成线程的区别,并给出了示例 2 的高度从 100px 变为 200px。两种动画方案的比较以及对主线程和合成线程整个工作流程的非常详细的解释。我真诚地建议您仔细阅读。
我们回过头来总结一下css3动画卡住的解决办法:在使用css3转场做动画效果时,优先考虑transform,尽量不要使用高度、宽度、边框和内边距。
transform为我们提供了缩放、折叠、旋转等丰富的API,但使用时要考虑兼容性。但实际上,对于大多数CSS3来说,移动端有更好的支持,桌面端需要特别关注。
附录:为了增加这篇文章的说服力,我回家做了一个实验。代码如下。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.margin-transition{
/* margin-left: 0; */
background: rgba(0,0,255,0.3);
transition: margin-left 1s;
}
.transform-transition{
/* transform: translate(0,0); */
background: rgba(0,255,0,0.3);
transition: transform 1s;
}
.common{
height: 300px;
width: 300px;
}
</style>
</head>
<body>
<div class="margin-transition common" id="marginTransition">
<p>transition:margin-left 1s</p>
</div>
<div class="transform-transition common" id="transformTransition">
<p>transition:tranform 1s</p>
</div>
<button id="control">见证奇迹</button>
<script>
var btn = document.getElementById('control');
var marginTransition = document.getElementById('marginTransition');
var transformTransition = document.getElementById('transformTransition');
btn.addEventListener("click",function(){
console.log(marginTransition.style,transformTransition.style)
marginTransition.style.marginLeft = "500px";
transformTransition.style.transform = "translate(500px,0)"
})
</script>
</body>
</html>
复制代码我主要会使用chrome devtools性能工具来比较两个工具的性能差异。首先我们看一下边框动画,动态调整DOM节点的左边框值,从0到500像素;。
transition: margin-left 1s;
复制代码我们再看一下transform的动画,动态调整transform的DOM节点值从translate(0,0)到translate(500px,0)。
transition: transform 1s;
复制代码图片可能不能很好地说明性能差异,所以让我们制作一个耗时的比较表,这将使我们的计算更加容易。
| 耗时 | 保证金 | transform | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 夏天 | 3518ms | 2286ms‶❙2286ms‶‶8ms 2.9ms | ||||||||
| 渲染 | 22 .5 ms | 6.9 ms | ||||||||
| 绘画 | 9.7 ms | 1.6 ms | ||||||||
| 其他 | 39.3 ms❙ CPU 或 GPU进行一些处理) | 3444.4ms | 2249.8 ms | |||||||
| GPU使用量 | 4.1MB | 1.7MB在CSS中转换效果时,我们可以通过3个差异表参数删除transform的功率差异和清晰余量。
|
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网