使用css3實(shí)現(xiàn)動(dòng)畫來開啟GPU加速

參考文章:
https://www.w3cplus.com/css3/introduction-to-hardware-acceleration-css-animations.html
http://blog.csdn.net/hsany330/article/details/50925260

用CSS3動(dòng)畫替代JS模擬動(dòng)畫的好處:

  1. 不占用JS主線程;

  2. 可以利用硬件加速;

  3. 瀏覽器可對(duì)動(dòng)畫做優(yōu)化(元素不可見時(shí)不動(dòng)畫減少對(duì)FPS影響)

下面讓我們來看一個(gè)動(dòng)畫效果,在該動(dòng)畫中包含了幾個(gè)堆疊在一起的球并讓它們沿相同路徑移動(dòng)。最簡(jiǎn)單的方式就是實(shí)時(shí)調(diào)整它們的 lefttop 屬性。我們可以使用JavaScript,但我們將使用CSS動(dòng)畫來替代。請(qǐng)注意,文中的示例不帶任何前綴,示例中使用了Autoprefixer來確保完整的兼容性。

.ball-running {
  animation: run-around 4s infinite;
}

@keyframes run-around {
  0%: {
    top: 0;
    left: 0;
  }

  25% {
    top: 0;
    left: 200px;
  }

  50% {
    top: 200px;
    left: 200px;
  }

  75% {
    top: 200px;
    left: 0;
  }
}

這里有一個(gè)動(dòng)畫按例,點(diǎn)擊按鈕啟動(dòng)一個(gè)JavaScript動(dòng)畫:

點(diǎn)擊“Start Animation”按鈕之后,你會(huì)隱約感覺到動(dòng)畫并不是那么流暢,即使使用電腦上的瀏覽器也會(huì)有些卡頓,更不要提在移動(dòng)端達(dá)到 60fps 的流暢效果了。為了解決這個(gè)問題,我們可以使用 CSS transform 中的 translate() 來替代 topleft

.ball-running {
  animation: run-around 4s infinite;
}

@keyframes run-around {
  0%: {
    transform: translate(0, 0);
  }

  25% {
    transform: translate(200px, 0);
  }

  50% {
    transform: translate(200px, 200px);
  }

  75% {
    transform: translate(0, 200px);
  }
}

現(xiàn)在動(dòng)畫看起來流暢多了。這是為什么呢?這是因?yàn)?transform 屬性不會(huì)觸發(fā)瀏覽器的 repaint,而 lefttop 則會(huì)一直觸發(fā) repaint,下圖是從 chrome 開發(fā)者工具的 timeline 面板監(jiān)測(cè)到的數(shù)據(jù):

CSS動(dòng)畫之硬件加速

上圖數(shù)據(jù)中的綠色條紋表示的就是使用 topleft 實(shí)現(xiàn)動(dòng)畫時(shí)瀏覽器發(fā)生的 repaint 操作,從中可以看出動(dòng)畫幀數(shù)遠(yuǎn)低于 60 幀。

下圖是使用CSS transform 檢測(cè)到的數(shù)據(jù):

CSS動(dòng)畫之硬件加速

如你所見,動(dòng)畫演示期間并沒有過多的 repaint 操作。

從 chrome 的開發(fā)者工具按 ESC 之后選擇 “rendering” 面板,我們可以通過選中“Enable piant flashing”來進(jìn)一步監(jiān)測(cè) repaint 操作。開啟該選項(xiàng)后,頁面中的 repaint 區(qū)域就會(huì)被綠色蒙版高亮顯示出來。重新使用 topleft 的示例演示的話,你會(huì)發(fā)現(xiàn)包裹球的那塊區(qū)域會(huì)一直閃爍綠色的蒙版。

CSS動(dòng)畫之硬件加速

另一方面,在使用 transform的示例中,綠色蒙版只會(huì)在動(dòng)畫開始和結(jié)束的時(shí)候出現(xiàn)。

那么,為什么 transform 沒有觸發(fā) repaint 呢?簡(jiǎn)而言之,transform 動(dòng)畫由GPU控制,支持硬件加速,并不需要軟件方面的渲染。

瀏覽器接收到頁面文檔后,會(huì)將文檔中的標(biāo)記語言解析為DOM樹。DOM樹和CSS結(jié)合后形成瀏覽器構(gòu)建頁面的渲染樹。渲染樹中包含了大量的渲染元素,每一個(gè)渲染元素會(huì)被分到一個(gè)圖層中,每個(gè)圖層又會(huì)被加載到GPU形成渲染紋理,而圖層在GPU中 transform 是不會(huì)觸發(fā) repaint 的,這一點(diǎn)非常類似3D繪圖功能,最終這些使用 transform 的圖層都會(huì)由獨(dú)立的合成器進(jìn)程進(jìn)行處理

在我們的示例中,CSS transform 創(chuàng)建了一個(gè)新的復(fù)合圖層,可以被GPU直接用來執(zhí)行 transform 操作。在chrome開發(fā)者工具中開啟“show layer borders”選項(xiàng)后,每個(gè)復(fù)合圖層就會(huì)顯示一條黃色的邊界:

示例中的球就處于一個(gè)獨(dú)立的復(fù)合圖層,移動(dòng)時(shí)的變化也是獨(dú)立的:

CSS動(dòng)畫之硬件加速

此時(shí),你也許會(huì)問:瀏覽器什么時(shí)候會(huì)創(chuàng)建一個(gè)獨(dú)立的復(fù)合圖層呢?事實(shí)上一般是在以下幾種情況下:

  • 3D 或者 CSS transform
  • <video><canvas> 標(biāo)簽
  • CSS filters
  • 元素覆蓋時(shí),比如使用了 z-index 屬性

等一下,上面的示例使用的是 2D transition 而不是 3D 的 transforms ?。窟@個(gè)說法沒錯(cuò),所以在timeline中我們可以看到:動(dòng)畫開始和結(jié)束的時(shí)候發(fā)生了兩次 repaint 操作。

CSS動(dòng)畫之硬件加速

3D 和 2D transform 的區(qū)別就在于,瀏覽器在頁面渲染前為3D動(dòng)畫創(chuàng)建獨(dú)立的復(fù)合圖層,而在運(yùn)行期間為2D動(dòng)畫創(chuàng)建。動(dòng)畫開始時(shí),生成新的復(fù)合圖層并加載為GPU的紋理用于初始化 repaint。然后由GPU的復(fù)合器操縱整個(gè)動(dòng)畫的執(zhí)行。最后當(dāng)動(dòng)畫結(jié)束時(shí),再次執(zhí)行 repaint 操作刪除復(fù)合圖層。

使用 GPU 渲染元素

并不是所有的CSS屬性都能觸發(fā)GPU的硬件加速,實(shí)際上只有少數(shù)屬性可以,比如下面的這些:

  • transform
  • opacity
  • filter

強(qiáng)制使用GPU渲染

為了避免 2D transform 動(dòng)畫在開始和結(jié)束時(shí)發(fā)生的 repaint 操作,我們可以硬編碼一些樣式來解決這個(gè)問題:

.example1 {
  transform: translateZ(0);
}

.example2 {
  transform: rotateZ(360deg);
}

這段代碼的作用就是讓瀏覽器執(zhí)行 3D transform。瀏覽器通過該樣式創(chuàng)建了一個(gè)獨(dú)立圖層,圖層中的動(dòng)畫則有GPU進(jìn)行預(yù)處理并且觸發(fā)了硬件加速。

開啟GPU硬件加速可能觸發(fā)的問題:

通過-webkit-transform:transition3d/translateZ開啟GPU硬件加速之后,有些時(shí)候可能會(huì)導(dǎo)致瀏覽器頻繁閃爍或抖動(dòng),可以嘗試以下辦法解決之:

-webkit-backface-visibility:hidden;
-webkit-perspective:1000;

如何監(jiān)測(cè)動(dòng)畫幀速率

推薦兩種實(shí)時(shí)監(jiān)測(cè)網(wǎng)頁渲染幀速率的方法:

1.Chrome的DevTool中TimeLine的Frame模塊

2.地址欄輸入”chrome:flags”搜索”fps”,將”FPS計(jì)數(shù)器”開啟,瀏覽器重啟后右上角會(huì)實(shí)時(shí)顯示幀速率。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 譯者序:原文GPU Animation: Doing It Right,發(fā)表于2016年12月6日,本文是對(duì)該篇的...
    smilewalker閱讀 1,724評(píng)論 0 8
  • 最近看到一篇關(guān)于GPU動(dòng)畫的神文,原文地址:https://www.smashingmagazine.com/20...
    purple_force閱讀 3,694評(píng)論 1 6
  • 在移動(dòng)端,我們經(jīng)常用到如上的CSS代碼實(shí)現(xiàn)所謂的“硬件加速”,來提高動(dòng)畫的流暢度。在部分情況下,我們的CSS動(dòng)畫的...
    天外來人閱讀 944評(píng)論 0 1
  • CSS3動(dòng)畫應(yīng)用很廣,尤其是在H5項(xiàng)目中,炫酷的交互效果可以給產(chǎn)品帶來更好的體驗(yàn),更能吸引用戶。然而在應(yīng)用的時(shí)候,...
    UIleader閱讀 2,316評(píng)論 0 7
  • 動(dòng)畫卡頓是在移動(dòng)web開發(fā)時(shí)經(jīng)常遇到的問題,解決這個(gè)問題一般會(huì)用到css3硬件加速。css3硬件加速這個(gè)名字感覺上...
    狐尼克朱迪閱讀 5,249評(píng)論 0 0

友情鏈接更多精彩內(nèi)容