画布径向渐变vs .png性能

时间:2016-05-22 07:43:47

标签: javascript performance canvas

我正在尝试使用HTML canvas元素模拟画笔。为了获得刷子硬度,我使用径向渐变,但我不完全确定为每个点创建一个新的径向渐变或者将径向渐变保存为图像是否更快,而是使用drawImage()。 / p>

当前代码:

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);

2 个答案:

答案 0 :(得分:4)

与基本上复制的图像相反,梯度的生成成本很高。虽然它们都需要经过变换矩阵和抗锯齿处理,但除此之外没有图像计算。

更新根据以下评论,人们似乎会根据浏览器和硬件获得极其可变的测试结果。嵌入式测试不是很准确,而是作为指针,因此我创建了一个 more accurate test here 。请随时在评论中发布以下结果 - 更新结束 -

以下不是世界上最准确的测试,但差异是如此之大,以至于在任何情况下都会得到一个非常好的指针:



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);
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

在渲染径向渐变时,您可以即时构建渐变,或者在引用时使用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的执行效果可能非常不同。还要注意,通过使用图像,您可能遇到分辨率问题(太高:性能,太低:锯齿),如果您使用渐变,则不会遇到这种问题。因此,即使渐变被证明较慢,您也可能更喜欢它,因为它始终如一。

几个问题:你经常改变你的硬度吗?你经常改变画笔大小吗?你改变渐变的开始/结束颜色?

只有通过回答这些问题并且随机设置的rect /硬度具有与您的实际用例相同的平均分布,您才能对其进行基准测试/比较。

最后一句话:如果很难说哪种解决方案更快,那么选择解决方案的时间依赖于...其他良好的原因......: - )