把 Canvas 放到 WebWorker 中去繪制?想都不敢想有多爽!
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎(chǔ)是進階的前提是我的初心!
最近項目中需要繪制一塊畫布,大致上樣子如下,就是繪制一堆人名在 Canvas 上(實際業(yè)務(wù)比這個復(fù)雜)。
圖片
大致代碼如下:
頁面肯定不止只有 Canvas 的邏輯,就比如我在繪制畫布后,想去計算 1-100 的數(shù)字總和。
圖片
但是最終發(fā)現(xiàn),繪制畫布耗費了很多時間,差不多有 1s 的時間,并且堵塞了主進程的代碼,導(dǎo)致了我后續(xù)的邏輯被堵住了,下圖可以看到,我的 computedTotal 結(jié)果是在畫布繪制完菜執(zhí)行完的。
圖片
所以繪制畫布的耗時過長,阻塞了后續(xù)的同步代碼邏輯,這是不合理的,我們需要做優(yōu)化。
Web Worker?(離屏 Canvas)
我們平時在遇到這類情況的時候,十有八九第一時間都會想到 Web Worker。
但是問題來了:正常來說,Web Worker 中可獲取不了 DOM,做不了畫布繪制呀。
估計會有人想:那我們可以把 Canvas 的 DOM 節(jié)點傳入 Web Worker 中嗎?
可以試試!
我們先準備一個 worker.js 來存放 Web Worker 的代碼:
圖片
接著在 index.js 中把 Canvas 的 DOM 節(jié)點傳過去。
圖片
發(fā)現(xiàn)會報錯,因為 postMessage 傳數(shù)據(jù)的時候會進行深拷貝,而 DOM 節(jié)點無法被深拷貝。
那么傳上下文過去可以嗎?也可以試試!
圖片
可以發(fā)現(xiàn),還是不行。
圖片
canvas.transferControlToOffscreen
不得不說 JavaScript 是真的強大,早就為我們準備好了一個 API ,那就是 transferControlToOffscreen。
圖片
有了這個 API ,我們就可以把 Canvas 的 DOM 節(jié)點以另一種方式傳入 Web Worker 了?。?!我們也能在 Web Worker 中去進行 Canvas 的繪制,進而優(yōu)化主線程的代碼執(zhí)行效率??!
首先改造一下 drawSunshine,現(xiàn)在只需要傳入 Canvas DOM,不需要在主線程去做繪制。
圖片
接著我們在 worker.js 中去接收 DOM 節(jié)點,并進行畫布繪制。
圖片
最終可以看到,Canvas 的繪制并不會阻塞后續(xù)邏輯的執(zhí)行。