position: absolute;_前端性能优化--transform与position
上個星期去yy語音面試,就有一個這樣問題: transform與position:absolute 有什么區別? 我回家后查資料發現這道題目其實不簡單啊,涉及到重排、重繪、硬件加速等網頁優化的知識。
首先看一個用top、left實現的動畫效果
<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>在運行的時候,會隱約覺得動畫的運行并不流暢,動畫有些停頓的感覺。這時因為top和left的改變會觸發瀏覽器的 reflow和 repaint 。然后整個動畫過程都在不斷觸發瀏覽器的重新渲染,這個過程是很影響性能的。
下面是chrome 瀏覽器performance中的監測到的數據。在 chrome的rendering面板中可以看到沒改變一次位置瀏覽器就要渲染一個。
然后我用transform 重寫一下這個動畫效果
<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>這時候會發現整個動畫效果流暢了很多,在動畫移動的過程中也沒有發生repaint和reflow。
下面是chrome 瀏覽器performance中的監測到的數據。以及rendering面板。
那么,為什么 transform 沒有觸發 repaint 呢?原因就是,transform 動畫由GPU控制,支持硬件加速。
看完以上兩個例子,那么我們就要入正題了。
主線程和合成線程
現代瀏覽器通常由兩個重要的線程組成(主線程 和 合成線程)。這兩個線程一起工作完成繪制頁面的任務:
主線程需要做的任務如下:
- 運行Javascript
- 計算HTML元素的CSS樣式
- layout (relayout)
- 將頁面元素繪制成一張或多張位圖
- 將位圖發送給合成線程
合成線程主要任務是:
- 利用GPU將位圖繪制到屏幕上
- 讓主線程將可見的或即將可見的位圖發給自己
- 計算哪部分頁面是可見的
- 計算哪部分頁面是即將可見的(當你的滾動頁面的時候)
- 在你滾動時移動部分頁面
在很長的一段時間內,主線程都在忙于運行Javascript和繪制元素。
例如,當用戶滾動一個頁面時,合成線程會讓主線程提供最新的可見部分的頁面位圖。然而主線程不能及時的響應。這時合成線程不會等待,它會繪制已有的頁面位圖。對于沒有的部分則繪制白屏。
GPU擅長的領域:
我們來看一個例子:將一個頁面元素的高度從100px漸變到200px,方法可以是:1、height 2、transform: scale(1.0)。兩個方法性能是不一樣的,現在我們來從主線程和合成線程的角度來看看
傳統的方法:改變 height
div {height: 100px;transition: height 1s linear; }div:hover {height: 200px; }下圖是一張主線程和合成線程的互相交互的時間線圖。
黃色盒子的操作是潛在耗時較長的,藍色盒子的操作是很快的。在transition動畫的每一幀中,都修改元素的高度,這可能會導致子元素的大小也會變化,然后瀏覽器不得不進行relayout。在relayout之后主線程還需要重新生成元素的位圖,加載位圖到GPU內存中
css3的方法:transform
直接改變元素的高度是很耗時的,但我們可以使用 transform: scale(); 來縮放元素,實現這個改變高度的目的。
div {transform: scale(0.5);transition: transform 1s linear; }div:hover {transform: scale(1.0); }黃色盒子的操作是潛在耗時較長的,藍色盒子的操作是很快的。CSS transform屬性并不會觸發當前元素或附近元素的relayout。瀏覽器將當前元素視為一個整體,它會縮放、旋轉、移動這一整個元素。
瀏覽器只需要在動畫開始之時生成位圖,然后將位圖發送給GPU。之后瀏覽器不需要做額外的relayout和repaint,甚至不需要發送位圖給GPU。瀏覽器只需要充分發揮GPU的長處:繪制同一張位圖到不同的位置、旋轉角度和縮放比例。
可以使用GPU加速的CSS3屬性
- CSS transform
- CSS opacity
- CSS filter
感想
既然transform這個屬性那么強大,我們就可以用他來優化我們平時的一下操作。例如:拖拽,在mouseover階段就用transform,在mousedown階段在再用position絕對定位,這樣是不是就可以減少repaint和reflow的操作呢。還有就是動畫。等等。
參考資料
CSS動畫之硬件加速
CSS animation和transition的性能探究
總結
以上是生活随笔為你收集整理的position: absolute;_前端性能优化--transform与position的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java单纯形法_单纯形法 - fjzz
- 下一篇: html前端页面的基本骨架是,web前端