transform和position
position + top/left的效果
下面我們來看一個(gè)動(dòng)畫效果(類似平時(shí)頁面滾動(dòng)功能)殿如,在該動(dòng)畫是讓一個(gè)球沿著某種路徑移動(dòng)猴娩。最簡(jiǎn)單的方式就是實(shí)時(shí)調(diào)整它們的left和top屬性,使用css動(dòng)畫實(shí)現(xiàn)些椒。
<style>
html,
body {
width: 100%;
height: 100%;
}
.ball-running {
animation: run-around 4s infinite;
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
@keyframes run-around {
0%: {
top: 0;
left: 0;
}
25% {
top: 0;
left: 200px;
}
50% {
top: 200px;
left: 200px;
}
75% {
top: 200px;
left: 0;
}
}
</style>
<body>
<div class="ball-running"></div>
</body>
在運(yùn)行的時(shí)候即使是在電腦瀏覽器上也會(huì)隱約覺得動(dòng)畫的運(yùn)行并不流暢妻往,更不要提在移動(dòng)端達(dá)到60fps的流暢效果了拗窃。這是因?yàn)閠op和left的改變會(huì)觸發(fā)瀏覽器的reflow和repaint棺蛛,整個(gè)動(dòng)畫過程都在不斷觸發(fā)瀏覽器的重新渲染枷畏,這個(gè)過程是很影響性能的瓮增。
transform效果
為了解決這個(gè)問題,我們使用transform中的translate()來替換top和left
<style>
html,
body {
width: 100%;
height: 100%;
}
.ball-running {
animation: run-around2 4s infinite;
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
@keyframes run-around2 {
0% {
transform: translate(0, 0);
}
25% {
transform: translate(200px, 0);
}
50% {
transform: translate(200px, 200px);
}
75% {
transform: translate(0, 200px);
}
}
</style>
<body>
<div class="ball-running"></div>
</body>
這個(gè)時(shí)候我們就會(huì)發(fā)現(xiàn)整個(gè)動(dòng)畫效果流暢了很多哩俭,在動(dòng)畫移動(dòng)的過程中也沒有發(fā)生repaint和reflow钉赁。那么為什么transform沒有出發(fā)repaint呢?原因就是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)行處理滑废,移動(dòng)時(shí)的變化也是獨(dú)立的蝗肪,不會(huì)影響到頁面的其他元素,造成重排重繪是因?yàn)橛绊懙巾撁娴钠渌麍D層元素導(dǎo)致的蠕趁,可以理解為其他元素都是在一個(gè)圖層空間薛闪,所以一個(gè)圖層移動(dòng)其他的也會(huì)收到影響,而transform創(chuàng)建了一個(gè)新的復(fù)合圖層俺陋,它會(huì)被GPU獨(dú)立執(zhí)行transform操作豁延,跟其他圖層互不影響,所以不會(huì)引起重排重繪腊状。
此時(shí)诱咏,你也許會(huì)問瀏覽器什么時(shí)候會(huì)創(chuàng)建一個(gè)獨(dú)立的復(fù)合圖層呢?事實(shí)上一般是在以下幾種情況下:
- 3D或者CSS transform
- video或canvas標(biāo)簽
- CSS filters
- 元素覆蓋時(shí)缴挖,比如使用了z-index屬性
等一下袋狞,上面的示例使用的是2Dtransform而不是3D的transform,因?yàn)樵趧?dòng)畫開始和結(jié)束的時(shí)候觸發(fā)了兩次repaint操作映屋。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ù)合圖層卵蛉。
transform為什么不會(huì)引發(fā)重排
因?yàn)镚PU進(jìn)程會(huì)為其開啟一個(gè)新的復(fù)合圖層,不會(huì)影響默認(rèn)復(fù)合圖層(就是普通文檔流)么库,所以并不會(huì)影響周邊的 DOM 結(jié)構(gòu)傻丝,而屬性的改變也會(huì)交給 GPU 處理,不會(huì)進(jìn)行重排诉儒。使 GPU 進(jìn)程開啟一個(gè)新的復(fù)合圖層的方式還有 3D 動(dòng)畫葡缰,過渡動(dòng)畫,以及 opacity 屬性忱反,還有一些標(biāo)簽泛释,這些都可以創(chuàng)建新的復(fù)合圖層。這些方式叫做硬件加速方式温算。你可以想象成新的復(fù)合圖層和默認(rèn)復(fù)合圖層是兩幅畫怜校,相互獨(dú)立,不會(huì)彼此影響注竿。降低重排的方式:要么減少次數(shù)茄茁,要么降低影響范圍,創(chuàng)建新的復(fù)合圖層就是第二種優(yōu)化方式巩割。絕對(duì)布局雖然脫離了文檔流裙顽,但不會(huì)創(chuàng)建新的復(fù)合圖層,因此當(dāng)絕對(duì)布局改變時(shí)宣谈,不會(huì)影響普通文檔流的 render tree锦庸,但是依然會(huì)繪制整個(gè)默認(rèn)復(fù)合圖層,對(duì)普通文檔流是有影響的蒲祈。普通文檔流就是默認(rèn)復(fù)合圖層甘萧,不要介意我交換使用它們?nèi)绻阋褂糜布铀俜绞浇档椭嘏诺挠绊懀?qǐng)不要過度使用梆掸,創(chuàng)建新的復(fù)合圖層是有額外消耗的扬卷,比如更多的內(nèi)存消耗,并且在使用硬件加速方式時(shí)酸钦,配合 z-index 一起使用怪得,盡可能使新的復(fù)合圖層的元素層級(jí)等級(jí)最高。
使用GPU渲染元素
能觸發(fā)GPU硬件加速的CSS屬性
(1)transform
(2)opacity
(3)filter
使用硬件加速需要注意的事項(xiàng)
(1)內(nèi)存卑硫。如果GPU加載了大量的紋理徒恋,那么很容易就會(huì)發(fā)生內(nèi)存問題,這一點(diǎn)在移動(dòng)端尤為明顯欢伏。
(2)使用GPU渲染會(huì)影響字體的抗鋸齒效果入挣。這是因?yàn)镚PU和CPU具有不同的渲染機(jī)制,即使最終硬件加速停止了硝拧,文本還是會(huì)在動(dòng)畫期間顯示的很模糊径筏。
總結(jié)
1葛假、transform會(huì)使用GPU硬件加速,性能更好滋恬,position + top/left會(huì)觸發(fā)大量的重排重繪聊训,性能影響較大。
2恢氯、硬件加速的工作原理是創(chuàng)建一個(gè)新的復(fù)合圖層带斑,然后使用合成線程進(jìn)行渲染
3、3D和2D動(dòng)畫的區(qū)別勋拟,2D動(dòng)畫會(huì)在動(dòng)畫開始和動(dòng)畫結(jié)束時(shí)觸發(fā)2次重新渲染
4勋磕、使用了GPU可以優(yōu)化動(dòng)畫小故宮但是不要濫用,會(huì)有內(nèi)存問題
5指黎、理解強(qiáng)制觸發(fā)硬件加速的transform技巧,使用對(duì)GPU友好的CSS屬性
參考文章:https://zhuanlan.zhihu.com/p/78230297
el-scrollbar是elementui自帶的頁面滾動(dòng)條州丹,如果用頁面滾動(dòng)條醋安,我們發(fā)現(xiàn)在ie瀏覽器下卡頓很明顯,但是用el-scrollbar滾動(dòng)頁面就會(huì)感覺會(huì)流暢很多墓毒,因?yàn)轫撁鏉L動(dòng)會(huì)引發(fā)重排重繪吓揪,但是el-scrollbar是用transform不會(huì)引起,所以用el-scrollbar會(huì)感覺流暢很多所计,轉(zhuǎn)訂單去掉overflow:hidden就會(huì)流暢是因?yàn)檫@個(gè)樣式會(huì)覆蓋el-scrollbar的樣式柠辞,