我正在研究一個基於HTML5的遊戲,我希望在網格中混合繪製成數百個方格的單元格的不同顏色的半圓形區域。效果就像熱圖。經過一番研究,我發現了Simon Sarris上面記錄的「陰影」技術。
實現這種技術實現了我想要的外觀。我喜歡這很容易理解。然而,在實踐中,我發現即使是少數(〜150)的陰影渲染,也比我之前用於繪製數千個填充矩形的技術(不過沒有吸引力)慢得多。
所以我決定做一些分析。我寫了一些基本的JavaScript(可在https://jsfiddle.net/Flatfingers/4vd22rgg/上看到一個修改版本),將5種不同形狀類型的2000個副本繪製到1250x600畫布的非重疊部分上,最後記錄這五個操作中每一個的運行時間五種主流桌面瀏覽器以及移動Safari的版本。 (對不起,桌面Safari,我也沒有Android的方便測試。)然後我嘗試了不同的效果組合,並記錄了經過的時間。
下面是如何我繪製兩個梯度具有相似的外觀,以陰影填充弧一個簡化的例子:
var gradient1 = context.createRadialGradient(75,100,2,75,100,80);
gradient1.addColorStop(0,"yellow");
gradient1.addColorStop(1,"black");
var gradient2 = context.createRadialGradient(125,100,2,125,100,80);
gradient2.addColorStop(0,"blue");
gradient2.addColorStop(1,"black");
context.beginPath();
context.globalCompositeOperation = "lighter";
context.globalAlpha = 0.5;
context.fillStyle = gradient1;
context.fillRect(0,0,200,200);
context.fillStyle = gradient2;
context.fillRect(0,0,200,200);
context.globalAlpha = 1.0;
context.closePath();
的時間設置
(2000不相重疊的形狀,集globalAlpha的,的drawImage()被用於梯度而不是陰影)
IE 11 (64-bit Windows 10)
Rects = 4 ms
Arcs = 35 ms
Gradients = 57 ms
Images = 8 ms
Shadows = 160 ms
Edge (64-bit Windows 10)
Rects = 3 ms
Arcs = 47 ms
Gradients = 52 ms
Images = 7 ms
Shadows = 171 ms
Chrome 48 (64-bit Windows 10)
Rects = 4 ms
Arcs = 10 ms
Gradients = 8 ms
Images = 8 ms
Shadows = 203 ms
Firefox 44 (64-bit Windows 10)
Rects = 4 ms
Arcs = 21 ms
Gradients = 7 ms
Images = 8 ms
Shadows = 468 ms
Opera 34 (64-bit Windows 10)
Rects = 4 ms
Arcs = 9 ms
Gradients = 8 ms
Images = 8 ms
Shadows = 202 ms
Mobile Safari (iPhone5, iOS 9)
Rects = 12 ms
Arcs = 31 ms
Gradients = 67 ms
Images = 82 ms
Shadows = 32 ms
觀測
- 其中填充圖案,充滿rects一貫在所有測試的瀏覽器和環境的最快運行。
- 在IE 11和Edge中填滿的圓弧(圓圈)比填充的矩形慢10倍,而其他主流瀏覽器中的慢了大約3.5倍。
- 漸變的速度比IE 11,Chrome 48和Opera 34中的反應速度慢大約3倍,但是在Firefox 44中速度要慢100倍(請參閱Bugzilla report 728453)。
- 通過drawImage()處理的圖像大約是所有桌面瀏覽器中填充矩形的1.5倍。
- 帶陰影的實心圓弧是最慢的,範圍從IE,Edge,Chrome和Opera中的實際直徑的50倍慢到Firefox的100倍。
- Chrome 48和Opera 34在除陰影填充圓弧之外的每種形狀都非常迅速,但它們並沒有比其他瀏覽器差。
- 當drawImage()繪製1000個形狀,其中shadowOffsetX或shadowOffsetY被賦予一個超出物理屏幕分辨率的值時,Chrome和Opera崩潰。
- IE 11和Edge比其他桌面瀏覽器繪製弧線和漸變要慢。
- drawImage()在移動Safari上很慢。繪製多個漸變和陰影弧比用drawImage()多次繪製一個副本更快。
- Firefox中的繪製對以前的操作非常敏感:繪製陰影和漸變使繪製弧線變慢。顯示最快的時間。
- Mobile Safari中的繪圖對以前的操作非常敏感:陰影會使漸變變慢;漸變和弧使drawImage()甚至比通常慢。顯示最快的時間。
分析
雖然shadowOffset特徵是混合形狀的簡單和直觀有效的方式,它是比所有其他技術顯著慢。這限制了其僅適用於繪製一些陰影的應用程序,並且不需要快速反覆繪製多個陰影。此外,當使用drawImage()加快速度時,給shadowOffsetX或shadowOffsetY一個大於3000的值會導致Chrome 48和Opera 34掛起將近一分鐘,消耗CPU週期,然後崩潰我的nVidia顯示驅動程序,即使在更新之後到最新版本。 (谷歌搜索沒有發現有關Chromium的錯誤報告,當大型shadowOffset和drawImage()一起使用時,它會描述此錯誤。)
對於需要混合模糊形狀的應用程序,最直觀的方法是將globalCompositeOperation 「更輕」,並使用帶有globalAlpha值的drawImage()重複繪製預製的徑向漸變,或者在需要使用不同顏色時繪製單獨的漸變。這不是重疊陰影的完美匹配,但它很接近,避免了按像素計算。 (但是,請注意,在移動Safari中,直接繪製陰影填充弧實際上比漸變和drawImage()更快)。將globalCompositeOperation設置爲「更淺」會導致IE 11和Edge在繪製弧中速度減慢大約10倍,並使用徑向漸變仍然比在所有主要桌面瀏覽器中使用陰影填充弧更快,並且只比移動Safari中的陰影填充弧要慢兩倍。
結論
如果你唯一的目標平臺是iPad/iPhone的,對於好看的混合形狀的陰影充滿弧線的最快方法。否則,迄今爲止我發現的所有主要桌面瀏覽器都具有可比較外觀的最快方法是繪製放射狀漸變,並將globalCompositeOperation設置爲「更輕」,並使用globalAlpha控制不透明度。
注:在我進行的繪圖測試中,有一些明顯的方法可以提高性能。特別是,將每個形狀的每個實例繪製到屏幕外緩衝區,然後將該整個緩衝區繪製到可見畫布上會顯着提高性能。但是這會否定這個測試的目標,即比較在可見畫布上繪製各種形狀的相對速度。
兩個漸變的重疊區域合併但不合並。 - 你能不能逐像素地描述合併? – 2012-04-12 09:11:46