簡體   English   中英

畫布徑向漸變與.png性能

[英]Canvas radial gradient vs .png performance

我正在嘗試使用HTML canvas元素模擬畫筆。 為了獲得筆刷的硬度,我使用了一個徑向漸變,但是我不完全確定為每個點創建一個新的徑向漸變還是將徑向漸變保存為圖像並使用drawImage()更快。

當前代碼:

var gradient = context.createRadialGradient(x, y, hardness * brushSize, x, y, brushSize);

gradient.addColorStop(0, color);
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');

context.fillStyle = gradient;
context.fillRect(x - halfBrushSize, y - halfBrushSize, brushSize, brushSize);

drawImage (除了創建圖像之外):

context.drawImage(img, x, y);

與基本為副本的圖像相反,生成漸變的代價很高。 雖然它們都需要經過變換矩陣和抗鋸齒處理,但是除此之外,沒有涉及圖像的計算。

更新從下面的評論中,根據瀏覽器和硬件的不同,人們似乎會獲得極其可變的測試結果。 嵌入式測試不是很准確,只能作為一個指針,因此,出於這個原因,我在這里創建了一個更准確的測試 隨時在下面的評論中發布結果。
-更新結束-

以下內容不是世界上最准確的測試,但是差異如此之大,無論如何您都會得到一個很好的指針,這是更快的:

 window.performance = window.performance || Date; setTimeout(go, 250); function go() { var ctx = c.getContext("2d"); // create radial gradient var gr = ctx.createRadialGradient(300, 300, 300, 300, 300, 0); gr.addColorStop(0, "#000"); gr.addColorStop(1, "#f00"); ctx.fillStyle = gr; // test gradient fill style var time1 = performance.now(); for (var i = 1000; i--;) ctx.fillRect(0, 0, c.width, c.height); var time2 = performance.now() - time1; o.innerHTML = "Gradient: " + time2.toFixed(4) + "<br>"; // test cached gradient (canvas = image source) ctx = c2.getContext("2d"); time1 = performance.now(); for (i = 1000; i--;) ctx.drawImage(c, 0, 0); time2 = performance.now() - time1; o.innerHTML += "drawImage: " + time2.toFixed(4); } 
 <output id=o>Running... please wait</output><br> <canvas id=c width=600 height=600></canvas><br> <canvas id=c2 width=600 height=600></canvas> 

渲染徑向漸變時,您可以即時構建漸變,也可以使用引用的png,但是還有第三種可能性:可以使用標准化的漸變,先構建一次,然后隨意使用通過使用上下文轉換,可以在任何位置/大小。

用於為給定硬度創建歸一化梯度的代碼如下:

var mySingleGradient =  ctx.createRadialGradient(0.5, 0.5, 0.5*hardness, 0.5, 0.5, 0.5);
mySingleGradient.addColorStop(0, color);
mySingleGradient.addColorStop(1, '#000');

就像使用png一樣,您會遇到為任何基色+硬度緩存漸變的問題。 但是您不會遇到任何png分辨率問題,並且最有可能的是,漸變的大小將比png的小得多。

您可以將這樣的歸一化梯度與結合使用:

function drawThatGradientHere(ctx, x, y, gradient, brushSize) {
    ctx.save();
    ctx.translate(x,y);
    ctx.scale(brushSize,brushSize);
    ctx.fillStyle = gradient;
    ctx.fillRect(0,0,1,1);
    ctx.restore();
}

我將不進行基准測試,因為有太多的機會可以比較蘋果和橙子而又不了解其用途。 因為例如,drawImage在使用縮放版本時可能會表現出很大的不同。 還請注意,通過使用圖像,您可能會遇到分辨率問題(太高:perf,太低:aliasing),如果您使用漸變則不會。 因此,即使事實證明漸變較慢,您也可能會喜歡它,因為它的外觀始終如一。

幾個問題:您經常改變硬度嗎? 您經常更改畫筆大小嗎? 您是否更改漸變的開始/結束顏色?

只需回答這些問題,並獲得一組隨機的rect / hards,它們具有與實際用例相同的平均分布,就可以進行基准測試/比較。

最后一句話:如果很難說出哪種解決方案更快,那就該依靠它來選擇解決方案了……另一個很好的理由……:-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM