過渡影片卡頓的解決方案
遇到這個問題的程序
發得快專案在優化時,有個優化是在切換選單時,讓選單有一個過渡影片,但是在切換到訂單時,過渡影片有一個明顯的卡頓,要做的就是解決這個卡頓,
代碼如下:(代碼為demo,公司代碼不可泄露)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#menu {
width: 100px;
height: 100px;
background: #000;
transition: all 2s;
color: #fff;
}
#menu.selected {
background: #f00;
}
</style>
</head>
<body>
<div id="menu">點擊觸發過渡影片</div>
<script>
let menu = document.getElementById("menu");
menu.onclick = function () {
// 計時器模擬異步http請求訂單
setTimeout(() => {
kill();
}, 500);
// 切換選中狀態
if (menu.classList.value.includes("selected")) {
menu.classList.remove("selected");
} else {
menu.classList.add("selected");
}
};
// while回圈卡住js兩秒,模擬訂單渲染阻塞
function kill() {
var start = +new Date();
while (+new Date() - start < 2000) {}
}
</script>
</body>
</html>
分析問題原因
首先分析卡頓原因,訂單界面資料量較大,渲染這個頁面需要較長的時間,js執行行程去渲染訂單表格時間過長,打斷了過度影片的計算,所以出現了卡頓的情況,
瀏覽器行程與執行緒分析
瀏覽器分為幾個行程
- 主行程
- 插件行程
- GPU行程
- 渲染行程(一個tab頁一個行程)
渲染行程又分為幾個執行緒
- GUI執行緒
- js執行執行緒
- dom事件執行緒
- 計時器執行緒
- http執行緒
關于這個案例,我們需要用到GPU行程,GUI執行緒與js執行執行緒
js執行執行緒主要負責執行js代碼,計算HTML 元素的 CSS 樣式,繪制位圖
GUI執行緒負責將js繪制好的位圖遞交給GPU行程,然后GPU行程渲染頁面
angular框架在拿到定單資料后做了什么?
拿到定單資料以后,將定單資料賦值給表格的data,angular框架的diff演算法計算出改變的虛擬dom節點,并開始繪制,但是50條資料過于龐大,繪制時間過久,造成了卡頓
如何解決
知道了問題是如何發生的,那么就可以思考解決方式,我目前找到了兩種方式可以解決這個問題
分散渲染時間
瀏覽器渲染50條資料時間太久,那么我們就不要一次渲染那么多,只渲染當前能看到的就可以,其他的以后再說,那么渲染的少了,卡頓時間自然也就少了
這種方法沒有降低總的渲染時間,只是將一大塊時間分散開了,那么在每段時間的間隔中,就可以繼續執行過渡影片的渲染
這種思路對應的解決方法是ng-zorro的虛擬滾動,類似懶加載
ng-zorro虛擬滾動示例
使用特定的css
在上網查資料的時候,發現了一個很有意思的demo
demo鏈接
同樣是js阻塞,憑什么transform可以繼續動,定位就卡住了呢?
帶著這個問題,去查閱資料
發現瀏覽器對一些css樣式有優化處理
深入瀏覽器理解CSS animations 和 transitions的性能問題
↑這個文章的圖片丟失了
圖片可以參考這個文章的圖片↓
CSS3 影片卡頓解決方案
所以是瀏覽器對transform,opacity,filter屬性有優化
猜測: 瀏覽器會優化這幾個樣式是因為,甭管這幾個樣式怎么變化,都不會影響到其他的dom元素,所以這部分的位圖只需要計算一遍就完事了,沒有必要重復遞交
那么根據這個思路我們改進代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#menu {
width: 100px;
height: 100px;
background: #000;
color: #f00;
transition: all 2s linear;
opacity: 0.2;
}
#menu.selected {
opacity: 1;
}
</style>
</head>
<body>
<div id="menu">點擊開始過渡影片</div>
<script>
let menu = document.getElementById("menu");
menu.onclick = function () {
setTimeout(() => {
kill();
}, 500);
if (menu.classList.value.includes("selected")) {
menu.classList.remove("selected");
} else {
menu.classList.add("selected");
}
};
function kill() {
var start = +new Date();
while (+new Date() - start < 2000) {}
}
</script>
</body>
</html>
這樣,通過opacity屬性,我們也解決了這個卡頓問題
但是這兩個方法都有缺點
懶加載方法如果加載的部分需要的時間也比較久的話(比如遇到垃圾電腦),那也會造成卡頓
而更改css屬性的方法,由于只有這么幾個屬性有優化效果,所以并不是所有的影片效果都可以做到的,而且這個方法只解決了卡頓,訂單表格加載慢的問題依然存在
所以以后遇到這種過渡影片卡頓的情況,最好把兩個方法結合起來
查資料三天,寫博客兩小時,點個贊噻?
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/250245.html
標籤:其他
