之前在研究一个有关 利用纯css完成感知悬停 的代码,在里面第一次见到了 will-change 属性(学识疏浅勿喷-=-),查资料看了一下张鑫旭大大的博客 使用CSS3 will-change提高页面滚动、动画等渲染性能 对这个属性肃然起敬(相遇恨晚,抱头痛哭.jpg)。

MDN上显示该属性语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
/* 关键字值 */
will-change: auto;
will-change: scroll-position;
will-change: contents;
will-change: transform; /* <custom-ident>示例 */
will-change: opacity; /* <custom-ident>示例 */
will-change: left, top; /* 两个<animateable-feature>示例 */
/* 全局值 */
will-change: inherit;
will-change: initial;
will-change: unset;

原理介绍

当我们通过某些行为(点击、移动或滚动)触发页面进行大面积绘制的时候,浏览器往往是没有准备的,只能被动使用CPU去计算与重绘,由于没有事先准备,应付渲染够呛,于是掉帧。will-change 是在行为触发之前告诉浏览器我们要进行一些什么样的变化操作,让浏览器好有个准备,启动GPU为你渲染动画。

  • CPU即中央处理器,它的功能主要是解释计算机指令以及处理计算机软件中的数据,也被称为主板。
    GPU即图形处理器,是与处理和绘制图形相关的硬件。
  • GPU是专为执行复杂的数学和几何计算而设计的,有了它,CPU就从图形处理的任务中解放出来,可以执行其他更多的系统任务。
  • 硬件加速是指在计算机中透过把计算量非常大的工作分配给专门的硬件来处理来减轻CPU的工作量的技术。在CSS transition, transform和animation的世界里,他暗示我们应该卸载进程到GPU,因此加快速度。这种情况通过向它自己的层叠加元素,当加载动画的时候可以加速渲染。

will-change 是怎样改善动画的性能和质量?

首先,在基于webkit的浏览器,我们在执行一些CSS的操作经常会看见闪烁,即二维变换和动画。在过去,我们通过欺骗浏览器一点点解决实现。我们会使浏览器执行3D变换,因此减轻了工作量到GPU上。当我们正确使用的时候,will-change属性将极大的帮助我们。


笔记

值得注意的一点,这个 will-change 应该在动画开始前的css语句块中执行,比如:

错误示例

1
2
3
4
5
.will-change:active {
will-change: transform;
transition: transform 0.3s;
transform: scale(1.5);
}

原因:当我们通知浏览器的时候,变化已经发生,完全抵消了will-change的全部意义。当预期的改变发生时,如果我们想要让浏览器提前了解,我们就必须在合适的时间通知它。 为了使元素达到激活的状态,它必须先被hover。

正确示例

1
2
3
4
5
6
7
8
9
.will-change {
transition: transform 0.3s;
}
.will-change:hover {
will-change: transform;
}
.will-change:active {
transform: scale(1.5);
}


不要直接写在默认状态中,因为will-change会一直挂着,如:
1
2
3
4
5
6
7
.will-change {
will-change: transform;
transition: transform 0.3s;
}
.will-change:hover {
transform: scale(1.5);
}

可以让父元素hover的时候,声明will-change,这样,移出的时候就会自动remove,触发的范围基本上是有效元素范围。

1
2
3
4
5
6
7
8
9
.will-change-parent:hover .will-change {
will-change: transform;
}
.will-change {
transition: transform 0.3s;
}
.will-change:hover {
transform: scale(1.5);
}

最后说一点,如果js想添加/删除will-change属性,应该按照如下操作:

1
2
3
4
5
6
7
8
9
10
dom.onmousedown = function() {
target.style.willChange = 'transform';
};
dom.onclick = function() {
// target动画哔哩哔哩...
};
target.onanimationend = function() {
// 动画结束回调,移除will-change
this.style.willChange = 'auto';
};

动画性能简易优化

  1. background-attachment: fixed; 换成 position: fixed;,因为前面的语句会在滚动的时候实时计算重绘。
  2. 背景图片所在的元素可以替换为 ::before 伪元素。
  3. 使用CSS3的 will-change 属性启动GPU渲染。

实例引用来:使用CSS3 will-change提高页面滚动、动画等渲染性能

参考资料:will-change - CSS | MDN

参考资料:关于CSS的will-change属性的介绍