不知道你有没有注意到,在基于Webkit的浏览器上进行一些CSS操作时,页面会出现卡顿或者闪烁的现象,尤其是在执行CSS的时候谈到动画,您可能以前听说过“硬件加速”这个词。CPU&GPU&硬件加速(HardwareAcceleration)简单来说,硬件加速就是浏览器会帮你把渲染页面的一些繁重任务交给GPU(GraphicsProcessingUnit),而不是把所有的大脑都交给CPU(Central处理单元)。)来处理,当这部分CSS操作被硬件加速时,可以使页面渲染速度更快。CPU在电脑主板上,相当于电脑的“大脑”。CPU几乎可以做任何事情。GPU位于计算机的显卡上,主要用于图形渲染。此外,GPU旨在执行图形渲染所需的复杂数学和图形。专为几何计算而设计,将一些运算移至GPU可以带来巨大的性能提升,减轻CPU的压力,尤其是在移动端。硬件加速(又名GPU加速)依赖于浏览器在呈现页面时使用的分层模型。当对页面上的元素执行某些操作(例如3D转换)时,相应的元素会提升到它们自己的层。独立于页面其余部分的渲染,在后期合成(绘制到屏幕上),让元素单独隔离,这样当页面上只有这个元素被变换(transform)时,其余的的元素不需要重新渲染,因此带来了速度提升的好处,值得一提的是,只有3D变换才有资格拥有自己的图层,2D变换则没有。CSS动画、变换和过渡属性不会由硬件自动加速,而是由浏览器的渲染引擎执行。但是,一些浏览器通过某些属性提供硬件加速,从而提高页面渲染性能。例如,CSS中的不透明度属性是少数可以被浏览器识别为硬件加速的属性之一,因为GPU可以轻松实现它。一般来说,任何想要通过CSS过渡或动画淡出不透明层的行为,浏览器都会将其丢给GPU以提高处理速度。在所有CSS属性中,opacity是性能最好的属性之一。其他常见的硬件加速操作有CSS3Dtransformhackmethodtohardwareacceleration:translateZ()ortranslate3d()usetranslateZ()(ortranslate3d())hack(有时称为nulltr??ansformhack)让浏览器对动画使用硬件加速或者通过向不会在3D空间中变换的元素添加简单的3D变换来变换行为。例如,通过在2D空间中添加简单的动画规则来实现硬件加速。transform:translate3d(0,0,0)硬件加速操作会创建一个所谓的复合层,会上传到GPU,由GPU合成,但是这种创建层的hack方法并不是万能的,层创建可以加快页面加载速度,但会带来其他成本:它会占用系统RAM和GPU上的内存(仅限于移动设备),而且很多时候效果不好(尤其是在移动设备上),因此要合理使用该方法,您一定要清楚知道使用这种方法是否真的可以提升页面的性能,不能让这种操作成为影响页面性能的瓶颈。除了这种创建图层的方法,CSS还引入了一个新的属性,可以让我们提前告知浏览器可能会对元素进行哪些操作,让浏览器提前优化处理那些可能比较耗性能的操作.在动画开始之前,提前处理好元素的动画行为。该属性是will-change新属性will-change的荣耀will-change属性可以让你提前通知浏览器你可能会对某个元素进行何种类型的操作,以便浏览器在需要时采取适当的优化方案.因此,避免了可能对页面响应性产生负面影响的不必要成本,从而使元素呈现速度更快。快速渲染和更新以获得更流畅的体验。例如,当在元素上使用CSS转换时,元素及其内容可能会被提升为层,如前所述,然后它们将被合成(绘制在屏幕上),但是将元素提升为新层的代价很高,这会使变换动画的开始延迟一秒钟的可观部分,从而导致明显的“闪烁”。为了避免这种情况的发生,我们可以提前通知浏览器,让浏览器提前做好准备,那么当同样的操作发生时,因为元素的layer已经准备好了,那么就可以马上进行过渡动画渲染了元素并快速更新页面。使用will-change向浏览器指示将发生转换。语法非常简单。will-change:transform还可以添加您要更改的确切属性的多个值。如:will-change:transform,opacity准确指定你想要改变的属性可以让浏览器更好地决定如何以更优化的方式处理这些改变,这显然比使用hack来强制浏览器更好创建可能无用的图形一种更好、更有效的分层方式will-change是否会对当前元素产生其他副作用,这取决于您提供的属性。如果属性的任何非初始值将在元素上创建堆叠上下文,则在will-change中指定属性将在元素上创建堆叠上下文。例如:使用clip-path属性和opcity属性的值不是初始值,两者都会在它们所应用的元素上创建一个堆叠上下文。因此,使用这些属性中的一个(或两个)作为will-change的值将在更改实际发生之前在元素上创建一个堆叠上下文,这同样适用于将在元素上创建堆叠上下文的其他属性另外,某些属性可能会导致为固定位置的元素创建一个包含块。例如,转换后的元素为其所有已定位的后代创建一个包含块,即使是那些已设置为position:fixed的后代。所以如果某个属性导致创建包含块,将其指定为will-change的值也会导致为固定位置元素生成包含块,所以如前所述,更改某些will-change属性会导致in创建一个新的合成层,但是,GPU不支持CPU在大多数浏览器中支持的子像素抗锯齿,因此有时它会导致内容模糊(尤其是文本),并且will-change属性不会直接影响对应的元素,它只是给浏览器一个预防针,让浏览器以更高效的方式渲染元素的内容。除了前面提到的某些情况下栈上下文和包含块的创建外,对对应的元素没有直接影响。使用will-change的注意事项不要使用will-change试图优化所有的操作,有时会带来适得其反的效果,使用起来更加智能合理,will-change也有一些副作用是无法直接检测到的,毕竟,它也只是一种与浏览器后台对话的方式,你不能指望它为你做所有事情,因为在使用这个属性时,请牢记以下几点,以确保造成伤害。不要使用will-change来声明对太多属性或元素的更改如前所述,让浏览器针对所有元素上所有属性的可能更改进行优化是很诱人的,因此也许可以编写以下代码*,*::before,*::after{will-change:all;}看起来很完美,其实问题很大。首先,all不是will-change的合法值。其次,这个Generalrules根本没用,它就像是告诉浏览器,所有这些属性都可能发生变化,需要优化,那么浏览器就和没有优化过的版本完全没有区别,因为没有优先级,也没有有用的信息.而像我们之前提到的hack方式,浏览器本身已经在做优化了,所以这样写是没有意义的,也不能忽略,因为浏览器处理will-change相关会占用大量的电脑资源属性,过度使用会使页面卡顿甚至崩溃,给浏览器足够的工作时间。will-change属性顾名思义:只通知浏览器已经发生的变化,所以在这个阶段什么都没有改变。我们使用will-change方便浏览器对我们声明的变化做一些优化,浏览器需要时间来处理和优化这些变化,为了让这些变化在真正发生的时候立即生效,所以设置will-changeimmediatelybeforeelementchanges几乎没有影响,可能比Notsetting更差,例如:.element:hover{will-change:transform;过渡:变换2s;transform:rotate(30deg)scale(1.5);}这几乎是在告诉浏览器优化已经发生的变化,这根本不起作用,也不符合will-change的定义。你应该想办法至少提前一点预测某种变化会发生,然后设置will-change的值。例如,当元素被点击时元素悬停时发生变化,然后在元素悬停时设置will-change属性,这将给浏览器足够的时间来优化变化,悬停元素和用户之间的时间实际上单击该元素足以让浏览器进行改进。.element{/*样式规则*/transition:transform1sease-out;}.element:hover{will-change:transform;}.element:active{transform:rotateY(180deg);}但如果我们期望的是鼠标悬停时如何改变?正如我们提到的,上面的代码也是无用的。在这种情况下,你通常仍然可以找到一些方法在动作发生之前预测它,例如,将鼠标悬停在目标元素的一个祖先元素上可以为浏览器提供足够的反应执行时间,因为鼠标悬停在它的一个祖先元素上不会always表示元素会与之交互,所以这个阶段可以进行设置will-change属性等操作悬停它的祖先*/.ancestor:hover.element{will-change:opacity;}/*当元素悬停时应用变化*/.element:hover{opacity:.5;}变化生效后移除Droppingwill-change浏览器针对即将发生的变化进行优化通常代价高昂,正如我们之前提到的,它会占用计算机的很大一部分资源,浏览器进行优化的通常行为是删除这些优化并尽快将其恢复到正常状态。飞行员。但是,will-change会覆盖这个行为,使得优化持续的时间比浏览器原来的时间长很多。正因为如此,记得去掉will-changeafteruse以释放资源。如果直接写Deadwill-change这个样式,语句是不能直接去掉的,所以基本推荐使用JS来处理。通过脚本,你可以在浏览器中声明你的更改,然后在更改完成后通过监听更改完成的时间来移除will-change。change,例如:我们之前提到过,可以通过监听对应元素(或者它的祖先元素)的mouseEnter事件来设置will-change,如果要让元素动起来,可以使用DOM事件animationEnd来监听当动画结束时,然后在animationEnd触发后移除will-change。//粗略的通用示例//获取将在单击时设置动画的元素,例如varel=document.getElementById('element');//设置当元素悬停时将发生变化del.addEventListener('mouseenter',hintBrowser);el.addEventListener('animationEnd',removeHint);functionhintBrowser(){//将要改变的优化属性//在动画的关键帧块中this.style.willChange='transform,opacity';}functionremoveHint(){this.style.willChange='auto';}可选择直接在CSS中使用will-change如前所述will-change用于向浏览器指示元素将在几毫秒内发生这是其中之一允许直接在css中编写will-changes的用例,尽管我们建议使用JavaScript来设置和取消设置will-changes,但在某些情况下,最好在css中设置(和持久化)是个不错的选择。举个例子:在少量元素上设置will-change,这些元素可能会被用户重复交互,应该快速响应用户的交互,因为元素的数量是有限的,这意味着所做的优化浏览器不会过度使用,因此不会造成太大的伤害,例如:在用户请求时通过将其滑出来变换侧边栏。下面的规则是合适的:.sidebar{will-change:transform;}另一个例子是在几乎不断变化的元素上使用will-change。例如,一个元素响应用户的鼠标移动并随着鼠标移动在屏幕上移动。这种情况下直接在css中声明will-change的值即可。烦人的元素卡在鼠标光标上{will-change:left,top;will-change的合法值will-change属性可以取四种可能的值:auto,scroll-position,contents,
