Home >Web Front-end >HTML Tutorial >[转] 使用CSS3 will-change提高页面滚动、动画等渲染性能 -张鑫旭_html/css_WEB-ITnose

[转] 使用CSS3 will-change提高页面滚动、动画等渲染性能 -张鑫旭_html/css_WEB-ITnose

WBOY
WBOYOriginal
2016-06-24 11:27:331082browse

一、先来看一个例子

下面这个例子来自某外文,我这里简单转述下。

视差滚动现在不是挺流行的嘛,然后Chris Ruppel当其使用background-attachment: fixed实现背景图片不随滚动条滚动而滚动效果的时候,发现,页面的绘制性能掉到了每秒30帧,这种帧频人眼已经可以感觉到一定的顿挫感了。

后来,参考一些其他同事还是同行的建议,做了一番优化,然后,页面的渲染性能——

这优化之前完全就是便秘,屎拉不出来的感觉;而优化之后,完全就是一泻千里,裤子都来不及脱的感觉。

一兄得便秘,在厕所里久久不能如便。
正在他极力努力的时候,看一哥们风一样的冲进厕所,进了他旁边的位置,刚进去就传来一真狂风暴雨,那兄羡慕的对那哥们说:哥们好羡慕你呀!
那哥们说:羡慕啥,裤子还没脱呢。。。

大家肯定会好奇,这到底施了什么魔法,可以让渲染提升如此之显著。3个小tips:

  1. background-attachment: fixed改成了position: fixed,因为前面这玩意滚动实时计算重绘;
  2. 背景图片所在的元素替换为::before伪元素;
  3. 使用了CSS3 will-change加速;

相关代码如下(假设类名是front):

.front::before {    content: '';    position: fixed; // 代替background-attachment    width: 100%;    height: 100%;    top: 0;    left: 0;    background-color: white;    background: url(/img/front/mm.jpg) no-repeat center center;    background-size: cover;    will-change: transform; // 创建新的渲染层    z-index: -1;  }

OK, 主角粉墨登场了,就是will-change, 这是什么鬼?

二、CSS3 will-change粉墨登场

CSS3 will-change属于web标准属性,虽然目前还是草案阶段,但出现已经有些时日了,兼容性这块Chrome/FireFox/Opera都是支持的。

这个属性作用很单纯,就是“增强页面渲染性能”。那它是如何增强的呢?

我们可能听听说过,3D transform会启用GPU加速①,例如translate3D, scaleZ之类,但是呢,这些属性业界往往称之为hack加速法。我们实际上不需要z轴的变化,但是还是假模假样地声明了,欺骗浏览器,这其实是一种不人道的做法。

① GPU即图形处理器,是与处理和绘制图形相关的硬件。GPU是专为执行复杂的数学和几何计算而设计的,可以让CPU从图形处理的任务中解放出来,从而执行其他更多的系统任务,例如,页面的计算与重绘。

而will-change则天生为此设计,顾名思意“我要变形了”,礼貌而友好。

几何老师:“同学们注意,我要开始变形了。” 

哈哈,别笑。真是这样的。

当我们通过某些行为(点击、移动或滚动)触发页面进行大面积绘制的时候,浏览器往往是没有准备的,只能被动使用CPU去计算与重绘,由于没有事先准备,应付渲染够呛,于是掉帧,于是卡顿。而will-change则是真正的行为触发之前告诉浏览器:“浏览器同学,我待会儿就要变形了,你心理和生理上都准备准备”。于是乎,浏览器同学把GPU给拉上了,从容应对即将到来的变形。

这其实很好理解的,对吧,提前预约从容不迫;突然造访手忙脚乱。

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

/* 关键字值 */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;

其中:
auto
就跟width:auto一样,实际上没什么卵用,昨天嘛,估计就是用来重置其他比较屌的值。

scroll-position
告诉浏览器,我要开始翻滚了。

contents
告诉浏览器,内容要动画或变化了。


顾名思意,自定义的识别。非规范称呼,应该是MDN自己的称呼,以后可能会明确写入规范。比方说animation的名称,计数器counter-reset, counter-increment定义的名称等等。

上面展示了2个例子,一个是transform一个是opacity,都是CSS3动画常用属性。如果给定的属性是缩写,则所有缩写相关属性变化都会触发。同时不能是以下这些关键字值:unset, initial, inherit,will-change, auto, scroll-position, 或 contents.


可动画的一些特征值。比方说left, top, margin之类。移动端,非transform, opacity属性的动画性能都是低下的,所以都是建议避免使用left/top/margin之流进行唯一等。但是,如果你觉得自己是margin属性奶大的,非要使用之,试试加个will-change:margin说不定也会很流畅(移动端目前支持还不是很好)。

就目前而言,使用的基本上都是:

.example {  will-change: transform;}

三、CSS3 will-change使用注意事项

will-change虽然可以加速,但是,一定一定要适度使用。那种全局都开启will-change等待模式的做法,无疑是死路一条。尼玛,用脚趾头想想也知道,你让浏览器各个元素都随时GPU渲染加速待命,还是妥妥搞死!

说到这里,想到了移动端的GPU加速。很多自以为然的同学写CSS3动画的时候,或者静态属性的时候,动不动就把translateZ之类GPU hack属性写上。同学们啊,GPU这玩意提高页面渲染性能它是有代价的呀,什么代价呢,就是手机的电量。你真以为有“既要马儿跑,又要马儿不吃草”的好事情啊!

平时,我们一般地CSS动画,平常的渲染处理,手机都是可以比较流畅的。完全没有必要以牺牲其他东西来实现。手机上的电量弥足珍贵。如果发现(尤其Android)机子h5页面不流畅,找找看是不是动画属性使用问题,或者非可视动画层没隐藏等等原因。

回到will-change. 同样的,will-change的使用也要谨慎,遵循最小化影响原则,所以,一开始的例子,才使用伪元素去搞,独立渲染(虽然我没看出来这个梗在什么地方)。

sitePoint网站上的这篇文章展示了几个处理例子:

不要这样直接写在默认状态中,因为will-change会一直挂着:

.will-change {  will-change: transform;  transition: transform 0.3s;}.will-change:hover {  transform: scale(1.5);}

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

.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, 事件或动画完毕,一定要及时remove. 比方说点击某个按钮,其他某个元素进行动画。点击按钮(click),要先按下(mousedown)再抬起才出发。因此,可以mousedown时候打声招呼, 动画结束自带回调,于是(示意,不要在意细节):

dom.onmousedown = function() {    target.style.willChange = 'transform';};dom.onclick = function() {    // target动画哔哩哔哩...};target.onanimationend = function() {    // 动画结束回调,移除will-change    this.style.willChange = 'auto';};

等。

四、参考文章

  • Fix scrolling performance with CSS will-change property
  • MDN:will-change
  • An Introduction to the CSS will-change Property
  • 本文内容均属于外文整理收集,加上自己理解书写。内容并未亲自实践验证,因此,不能保证100%正确,仅供大家学习参考。

    如果文中有什么表述不准确的地方,欢迎大力指正,感谢阅读,欢迎交流!

    本文为原创文章,包含脚本行为,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
    本文地址:http://www.zhangxinxu.com/wordpress/?p=5025

    (本篇完)

    Statement:
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn