详解盒子端CSS动画性能提升(3)

2.Graphics Layer 虽好,但不是越多越好,每一帧的渲染内核都会去遍历计算当前所有的 Graphics Layer ,并计算他们下一帧的重绘区域,所以过量的 Graphics Layer 计算也会给渲染造成性能影响。

记住这两点之后,回到上面我们说的坑。

假设我们有一个轮播图,有一个 ul 列表,结构如下:

<div> <div>轮播图</div> <ul> <li>列表li</li> <li>列表li</li> <li>列表li</li> <li>列表li</li> </ul> </div>

假设给他们定义如下 CSS:

.swiper { position: static; animation: 10s move infinite; } .list { position: relative; } @keyframes move { 100% { transform: translate3d(10px, 0, 0); } }

由于给.swiper添加了translate3d(10px, 0, 0)动画,所以它会生成一个 Graphics Layer,如下图所示,用开发者工具可以打开层的展示,图形外的黄色边框即代表生成了一个独立的复合层,拥有独立的 Graphics Layer 。

详解盒子端CSS动画性能提升

但是!在上面的图中,我们并没有给下面的list也添加任何能触发生成 Graphics Layer 的属性,但是它也同样也有黄色的边框,生成了一个独立的复合层。

原因在于上面那条元素有一个 z-index 较低且包含一个复合层的兄弟元素。我们并不希望list元素也生成 Graphics Layer ,但是由于 CSS 层级定义原因,下面的 list 的层级高于上面的 swiper,所以它被动的也生成了一个 Graphics Layer 。

使用 Chrome,我们也可以观察到这种层级关系,可以看到.list的层级高于.swiper:

详解盒子端CSS动画性能提升

所以,下面我们修改一下 CSS ,改成:

.swiper { position: relative; z-index: 100; } .list { position: relative; }

这里,我们明确使得.swiper的层级高于.list,再打开开发者工具观察一下:

详解盒子端CSS动画性能提升

可以看到,这一次,.list元素已经没有了黄色外边框,说明此时没有生成 Graphics Layer 。再看看层级图:

详解盒子端CSS动画性能提升

此时,层级关系才是我们希望看到的,.list元素没有触发生成 Graphics Layer 。而我们希望需要硬件加速的.swiper保持在最上方,每次动画过程中只会独立重绘这部分的区域。

总结

这个坑最早见于张云龙发布的这篇文章CSS3硬件加速也有坑,这里还要总结补充的是:

GPU 硬件加速也会有坑,当我们希望使用利用类似transform: translate3d()这样的方式开启 GPU 硬件加速,一定要注意元素层级的关系,尽量保持让需要进行 CSS 动画的元素的z-index保持在页面最上方。

Graphics Layer 不是越多越好,每一帧的渲染内核都会去遍历计算当前所有的 Graphics Layer ,并计算他们下一帧的重绘区域,所以过量的 Graphics Layer 计算也会给渲染造成性能影响。

可以使用 Chrome ,用上面介绍的两个工具对自己的页面生成的 Graphics Layer 和元素层级进行观察然后进行相应修改。

上面观察页面层级的 chrome 工具非常吃内存?好像还是一个处于实验室的功能,分析稍微大一点的页面容易直接卡死,所以要多学会使用第一种观察黄色边框的方式查看页面生成的 Graphics Layer 这种方式。

4. 使用 will-change 可以在元素属性真正发生变化之前提前做好对应准备

// 示例 .example { will-change: transform; }

上面已经提到过 will-change 了。

will-change 为 web 开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。 这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。

值得注意的是,用好这个属性并不是很容易:

在一些低端盒子上,will-change会导致很多小问题,譬如会使图片模糊,有的时候很容易适得其反,所以使用的时候还需要多加测试。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygdgf.html