“Lift not the painted veil which those who live
Call Life: though unreal shapes be pictured there,
And it but mimic all we would believe”
每個網頁或多或少都涉及到一些CSS動畫 通常簡單的動畫對于性能的影響微乎其微 然而如果涉及到稍顯復雜的動畫 不當的處理方式會使性能問題變得十分突出 幾個禮拜前在公司做了個presentation 標題是Faster Animation with GPU accelerated CSS本文是對此的文字總結
之前參與過的兩個項目里都要求用原生JS去實現對于網頁中某個元素的位置進行持續而頻繁的改變 我遇到的問題是動畫的卡頓甚至停滯 搜尋了很久解決方法 甚至比對了我的代碼和Github上完成相同功能的插件代碼的差異 最后通過改變幾個CSS屬性很大程度上改善了動畫
我們都知道 如果要在一個頁面上移動一個現有的元素 通常有四種方法 比如說改變元素的margin而這幾種方法的性能各異 通過測試不難看出 給元素的transform屬性設置translate3d(x,y,z)是最快的方法
這其實和網頁的渲染過程有關transform: translate3d(x,y,z)這一行代碼使得GPU去渲染動畫主體所在的層 而并非CPU 所以一定程度上提高了動畫的速度 各大瀏覽器對于GPU渲染過程并沒有一個清晰明了的概念 于是我參照了唯一較為詳細敘述整個流程的一篇文章GPU accelerated compositing in chrome
網頁渲染過程
關于Chrome瀏覽器渲染網頁的過程及其與GPU的關系 可以總結出以下三點:
? ? DOM中的每個節點都直接或間接地對應一個層
? ? 一些層有自己的支撐平面(backing surface) 這些層被稱為復合層(compositing layers)
? ? 對于復合層(compositing layers)來說compositor是利用GPU將它最終渲染到屏幕上的
復合層形成條件
而形成由GPU渲染的復合層(compositing layers) 需要滿足以下條件之一:
? ? 這個層對應的元素里有<canvas>
? ? 這個層里的元素使用了CSS動畫去改變透明度或者使用了-webkit-transform屬性
? ? 這個層里的元素使用了CSSfilter
Tips
對于那些即將參與CSS動畫的HTML元素 可以加上will-change這個屬性 使瀏覽器提前有所準備 但是注意不能濫用
當需要不斷改變一個元素的位置時 最好的方式是使用transform: translate3d(x,y,z)
我們還可以參照csstriggers這個網站去查看我們使用的單個的CSS屬性會給瀏覽器帶來哪些工作量