繁体   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