1. CPU和GPU

  • CPU即中央处理器,它的功能主要是解释计算机指令以及处理计算机软件中的数据,也被称为主板。

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

  • 硬件加速(或者说GPU加速)是指在计算机中透过把计算量非常大的工作分配给专门的硬件来处理来减轻CPU的工作量的技术。在CSS transition, transform和animation的世界里,他暗示我们应该卸载进程到GPU,因此加快速度。这种情况通过向它自己的层叠加元素,当加载动画的时候可以加速渲染。

  • 硬件加速依赖于浏览器渲染页面使用的layering model,当特定的操作(CSS 3D变形)作用于页面上的一个元素,元素移动到它自己的layer,在这个layer中元素合一不受页面其他元素的干扰独立渲染,然后复合到页面中去。在这种隔离内容渲染的工作方式下,如果页面的变化仅仅是该元素的变形,其余部分不必被重新渲染,这会带来显著的速度优势。值得注意的是只有3D变形会有自己的layer,2D变形不会。

  • CSS的动画、变形、渐变并不会自动的触发GPU加速,而是使用浏览器稍慢的软件渲染引擎。然而一些浏览器提供了hardware acceleration by means of certain properties来获取更高的渲染性能。 举个例子,opacity属性是几个能够加速的属性之一,因为GPU可以方便的处理。基本上任何层的透明度渐变浏览器都会交给GPU处理来加速。除了opacity能够使用GPU处理的就是CSS 3D变形了

2. translateZ() (or translate3d()) Hack

我们都通过translateZ()或者translate3d() hack来骗取浏览器触发硬件加速,具体做法就是为元素添加没有变化的3D变形,比如元素在2维空间可以通过添加以下CSS来硬件加速

transform: translate3d(0, 0, 0);

然而强制使用hack方式创建layer并不是长久之计,创建layer的技术可以使页面加速,但是也有代价,它们占用RAM和GPU存储空间(考虑到移动设备的存储容量有限),所以必须小心使用,确保这么做真的对页面渲染有所帮助。为了避免创建layer的hacks,一个允许我们提前通知浏览器我们将对元素做何种变化的CSS属性被引入,这样浏览器可以优化处理元素渲染的方式,为元素提前准备昂贵的动画处理操作,这就是wiil-change属性。

3.wiil-change

  • will-change属性可以提前通知浏览器我们要对元素做什么动画,这样浏览器可以提前准备合适的优化设置。这样可以避免对页面响应速度有重要影响的昂贵成本。元素可以更快的被改变,渲染的也更快,这样页面可以快速更新,表现的更加流畅。

  • 当对于素使用 CSS 3D变形时,元素及其内容可以在合成到页面之前被创建到我们之前说的layer。然而把元素放到layer中是个昂贵的操作,这将会导致变形动画延迟一个课件的瞬间,也就是flicker

    为了避免这种延时,我们可以在发生之前通知浏览器,这样浏览器会有一定的时间去准备这些变化,当发生的时候layer已经准备好了,这样动画酒会很流畅,不会闪屏。

will-change: transform;

可以写多个属性变化,逗号隔开

will-change: transform, opacity;

注意事项:

  • 不要将 will-change 应用到太多元素上:浏览器已经尽力尝试去优化一切可以优化的东西了。有一些更强力的优化,如果与 will-change 结合在一起的话,有可能会消耗很多机器资源,如果过度使用的话,可能导致页面响应缓慢或者消耗非常多的资源。滥用会使页面崩溃。。。
*,
*::before,
*::after {
will-change: all;
}

虽然看起来很屌,但其实对页面渲染伤害很大,这样的规则设了和没设没什么区别,浏览器本来就尝试最优的渲染所有元素,就等于你让老师重点照顾班里每个同学一样,就是废话!

其实这甚至是有害的,因为一些操作会占用太多的资源,甚至会导致页面奔溃,就等于强制要求老师为每个学生补课,累死了。。。

  • 有节制地使用:通常,当元素恢复到初始状态时,浏览器会丢弃掉之前做的优化工作。但是如果直接在样式表中显式声明了 will-change 属性,则表示目标元素可能会经常变化,浏览器会将优化工作保存得比之前更久。所以最佳实践是当元素变化之前和之后通过脚本来切换 will-change 的值。

  • 不要过早应用 will-change 优化:如果你的页面在性能方面没什么问题,则不要添加 will-change 属性来榨取一丁点的速度。 will-change 的设计初衷是作为最后的优化手段,用来尝试解决现有的性能问题。它不应该被用来预防性能问题。过度使用 will-change 会导致大量的内存占用,并会导致更复杂的渲染过程,因为浏览器会试图准备可能存在的变化过程。这会导致更严重的性能问题。

  • 给它足够的工作时间:这个属性是用来让页面开发者告知浏览器哪些属性可能会变化的。然后浏览器可以选择在变化发生前提前去做一些优化工作。所以给浏览器一点时间去真正做这些优化工作是非常重要的。使用时需要尝试去找到一些方法提前一定时间获知元素可能发生的变化,然后为它加上 will-change 属性。

在变化前立即为元素添加will-change几乎没有作用,可能还不如不设置,因为会导致新的layer创建,如下:

.element:hover {
will-change: transform;
transition: transform 2s;
transform: rotate(30deg) scale(1.5);
}

需要给浏览器足够的时间,如下:

.element {
/* style rules */
transition: transform 1s ease-out;
}
.element:hover {
will-change: transform;
}
.element:active {
transform: rotateY(180deg);
}

will-change顾名思义,通知浏览器即将发生的变化,而不是正在发生的变化。使用will-change,我们要求浏览器重点照顾我们声明的元素,为了这个浏览器需要一定的时间来组织优化操作,这样当变化发生的时候,优化才能没有延迟的作用到元素

语法:

/* 关键字值 */
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 ##
表示没有特别指定哪些属性会变化,浏览器需要自己去猜,然后使用浏览器经常使用的一些常规方法优化。
## <animateable-feature> ##
1) scroll-position 告诉浏览器,要不久后动画啦(改变滚动条的位置或者使之产生动画)
2) contents:告诉浏览器 不久后改变元素内容中的某些东西,或者使它们产生动画。
## <custom-ident> ##
不久后改变指定的属性名或者使之产生动画。如果属性名是简写,则代表所有与之对应的简写或者全写的属性。

浏览器兼容性:

Desktop

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support 36 36 (36)[1] 未实现 24 未实现

Mobile

Feature Android Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile
Basic support 37 36.0 (36) [1] 未实现 未实现 未实现

【MARK】 文档以整理记录为主,如有错误,欢迎指出哟,大家一起来学习...

csss3属性 — will-change的更多相关文章

  1. 关于checkbox的checked属性和change事件

    jquery中的attr和prop有什么区别? To retrieve and change DOM properties such as the checked, selected, or disa ...

  2. jq select change下拉框选项变化判断选中值,添加(attr)或移除(removeAttr)一个或多个属性

    select change下拉框选项变化判断选中值,添加(attr)或移除(removeAttr)一个或多个属性 $("#IsRecommend").change(function ...

  3. ebay API属性

    Ebay Trading API整理 纠纷相关 AddDispute:创建一个未支付纠纷 或 取消 a single line item order AddDisputeResponse:回复/关闭d ...

  4. vue-learning:28 - component - 组件事件的修饰符`.native / .sync`,以及组件属性`model`

    组件事件的修饰符.native / .sync,以及组件属性model .native 原生事件修饰符 在一个组件中,如果我们为其绑定一个原生的点击事件@click,基本是无效的. 在vue中对组件绑 ...

  5. vue学习-第三个DEMO(计算属性和监视) v-model基础用法

    <div id="demo"> 姓:<input type="text" placeholder="First Name" ...

  6. AlloyTouch 0.2.0发布--鱼和熊掌兼得

    原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/AlloyTouch-0.2.0 背景 公司师姐昨日在KM发了篇长文,主要结论RAF+transfo ...

  7. Backbone事件模块及其用法

    事件模块Backbone.Events在Backbone中占有十分重要的位置,其他模块Model,Collection,View所有事件模块都依赖它.通过继承Events的方法来实现事件的管理,可以说 ...

  8. 【转】Backbone使用总结

    转自  http://www.pchou.info/javascript/2014/06/26/backbone-summary-01.html 开始在项目中大规模使用backbone,一路磕磕碰碰, ...

  9. 对atime、mtime和ctime的研究

    前期准备 在实验之前我们在讨论为何会出现两种修改时间,为此我们推测因为修改的不是文件的同一数据,或者说同一地方,那么我们就要先搞清楚文件的结构. linux文件系统是Linux系统的心脏部分,提供了层 ...

随机推荐

  1. Event Bus & Event Emitter

    Event Bus & Event Emitter Event Bus https://code.luasoftware.com/tutorials/vuejs/parent-call-chi ...

  2. Nestjs mongodb

    nestjs 文档 mongoose 文档 使用"@meanie/mongoose-to-json"转换查询后返回的json数据 将"_id"转为"i ...

  3. js form.onformData事件

    在表单提交前修改数据,此事件在submit之后 f1.addEventListener("formdata", (e) => { e.formData.append(&quo ...

  4. NGK每日快讯」2021.1.27日NGK公链第85期官方快讯!

  5. Word带数学公式发布博客

    Word公式编辑器无法直接上传博客,一个一个的转换LaTeX还要加$,十分麻烦. 下面是我昨天摸索出来的办法.作为博客新人,这个问题困扰我一晚上,能解决我也是非常高兴的. 如果各位前辈有好方法的话,请 ...

  6. 用铁电存储器FRAM让穿戴式设备更省电

    可穿戴设备应用中的显示屏消耗了大部分电池电力.解决方法之一是直接提高电池容量,但是大容量电池会加大尺寸和重量,对可穿戴设备不合适,尤其是在市场不断追求更小型化的新款产品时更是如此.更具挑战性的是电池技 ...

  7. luogu4464:莫比乌斯反演,积性函数和伯努利数

    题目链接:https://www.luogu.com.cn/problem/P4464 简记$gcd(x,y)=(x,y)$. 推式子: $\sum_{i=1}^{n}{(i,n)^xlcm(i,n) ...

  8. C语言柔性数组和动态数组

    [前言]经常看到C语言里的两个数组,总结一下. 一.柔性数组 参考:https://www.cnblogs.com/veis/p/7073076.html #include<stdio.h> ...

  9. nc替代ping

    linux nc介绍: 语 法:nc [-hlnruz][-g<网关...>][-G<指向器数目>][-i<延迟秒数>][-o<输出文件>][-p< ...

  10. C#后端接收前端的各种类型数据

    前端往后端提交数据的方式常用的就这么三种:1.form提交:2.url参数提交:3.json提交 1.针对表单form方式的提交 在后端使用Request.Form的方式接收,比如 前端代码片段: v ...