在 HTML5 画布中设置单个像素的最佳方式是什么?

新手上路,请多包涵

HTML5 Canvas 没有明确设置单个像素的方法。

可以使用非常短的线来设置像素,但抗锯齿和线帽可能会干扰。

另一种方法可能是创建一个小的 ImageData 对象并使用:

 context.putImageData(data, x, y)

把它放在适当的位置。

任何人都可以描述一种有效且可靠的方法吗?

原文由 Alnitak 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 320
2 个回答

有两个最佳竞争者:

  1. 创建一个1×1的图像数据,设置颜色,以及 putImageData 位置:
    var id = myContext.createImageData(1,1); // only do this once per page
   var d  = id.data;                        // only do this once per page
   d[0]   = r;
   d[1]   = g;
   d[2]   = b;
   d[3]   = a;
   myContext.putImageData( id, x, y );

  1. 使用 fillRect() 绘制一个像素(应该没有锯齿问题):
    ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
   ctx.fillRect( x, y, 1, 1 );

您可以在此处测试这些速度:http: //jsperf.com/setting-canvas-pixel/9 或此处 https://www.measurethat.net/Benchmarks/Show/1664/1

我建议针对您关心的浏览器进行测试以获得最大速度。 截至 2017 年 7 月, fillRect() 在 Firefox v54 和 Chrome v59 (Win7x64) 上快 5-6 倍。

其他更愚蠢的选择是:

  • 在整个画布上使用 getImageData()/putImageData() ;这比其他选项慢大约 100 倍。

  • 使用数据 url 创建自定义图像并使用 drawImage() 显示它:

   var img = new Image;
  img.src = "data:image/png;base64," + myPNGEncoder(r,g,b,a);
  // Writing the PNGEncoder is left as an exercise for the reader

  • 创建另一个 img 或画布,其中填充了您想要的所有像素并使用 drawImage() 仅对您想要的像素进行 blit。这可能会非常快,但有一个限制,即您需要预先计算所需的像素。

请注意,我的测试不会尝试保存和恢复画布上下文 fillStyle ;这会降低 fillRect() 性能。另请注意,我不是从零开始,也不是为每个测试测试完全相同的像素集。

原文由 Phrogz 发布,翻译遵循 CC BY-SA 3.0 许可协议

尚未提及的一种方法是使用 getImageData,然后使用 putImageData。

当您想快速快速地一次性绘制很多时,此方法非常有用。

http://next.plnkr.co/edit/mfNyalsAR2MWkccr

 var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
var id = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var pixels = id.data;

var x = Math.floor(Math.random() * canvasWidth);
var y = Math.floor(Math.random() * canvasHeight);
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
var off = (y * id.width + x) * 4;
pixels[off] = r;
pixels[off + 1] = g;
pixels[off + 2] = b;
pixels[off + 3] = 255;

ctx.putImageData(id, 0, 0);

原文由 PAEz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题