在HTML5canvas上绘制点

通过使用context.moveTo()context.lineTo()函数,在HTML5canvas上绘制线条非常简单。

我不太确定是否可以绘制一个点,即单个像素的颜色。 lineTo函数不会绘制单个像素行(显然)。

有没有办法做到这一点?

出于性能原因,如果可以避免,请不要画圆。 只需绘制一个宽度和高度为1的矩形:

 ctx.fillRect(10,10,1,1); // fill in the pixel at (10,10) 

如果您计划绘制大量像素,则使用canvas的图像数据进行像素绘制会更有效率。

 var canvas = document.getElementById("myCanvas"); var canvasWidth = canvas.width; var canvasHeight = canvas.height; var ctx = canvas.getContext("2d"); var canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight); // That's how you define the value of a pixel // function drawPixel (x, y, r, g, b, a) { var index = (x + y * canvasWidth) * 4; canvasData.data[index + 0] = r; canvasData.data[index + 1] = g; canvasData.data[index + 2] = b; canvasData.data[index + 3] = a; } // That's how you update the canvas, so that your // // modification are taken in consideration // function updateCanvas() { ctx.putImageData(canvasData, 0, 0); } 

比你可以这样使用它:

 drawPixel(1, 1, 255, 0, 0, 255); drawPixel(1, 2, 255, 0, 0, 255); drawPixel(1, 3, 255, 0, 0, 255); updateCanvas(); 

欲了解更多信息,你可以看看这个Mozilla的博客文章: http : //hacks.mozilla.org/2009/06/pushing-pixels-with-canvas/

这看起来很奇怪,但HTML5支持绘制线条,圆形,矩形和其他许多基本形状,它没有任何适合绘制基本点的东西。 唯一的办法就是用你所拥有的任何一个模拟一个点。

所以基本上有三种可能的解决scheme:

  • 画一条线
  • 将点画成多边形
  • 将点画成一个圆

他们每个人都有他们的缺点。


线

 function point(x, y, canvas){ canvas.beginPath(); canvas.moveTo(x, y); canvas.lineTo(x+1, y+1); canvas.stroke(); } 

请记住,我们正在向东南方向发展,如果这是边缘,可能会出现问题。 但是你也可以在其他方向上画画。


长方形

 function point(x, y, canvas){ canvas.strokeRect(x,y,1,1); } 

或者以更快的方式使用fillRect,因为渲染引擎将只填充一个像素。

 function point(x, y, canvas){ canvas.fillRect(x,y,1,1); } 

圈子的问题之一是引擎渲染它们更困难

 function point(x, y, canvas){ canvas.beginPath(); canvas.arc(x, y, 1, 0, 2 * Math.PI, true); canvas.stroke(); } 

与矩形相同的想法,你可以用填充来实现。

 function point(x, y, canvas){ canvas.beginPath(); canvas.arc(x, y, 1, 0, 2 * Math.PI, true); canvas.fill(); } 

所有这些解决scheme的问题:

  • 很难跟踪你要画的所有点。
  • 当你放大时,它看起来很丑

如果你想知道什么是最好的方法来画一个点 ,我会去填充矩形。 你可以在这里看到我的jsperf与比较testing

在我的Firefox这个技巧的作品:

 function SetPixel(canvas, x, y) { canvas.beginPath(); canvas.moveTo(x, y); canvas.lineTo(x+0.4, y+0.4); canvas.stroke(); } 

小偏移在屏幕上不可见,但强制渲染引擎实际绘制一个点。

上面的说法是:“如果你打算绘制很多像素,使用canvas的图像数据进行像素绘制要高效得多”,这似乎是相当错误的 – 至less在Chrome 31.0.1650.57 m或取决于在你的“像素很多”的定义。 我宁愿直接发表评论,但不幸的是,我还没有足够的计算点:

我认为我正在绘制“很多像素”,因此我首先遵循了相应的build议,以便于后续将我的实现更改为每个绘制点的简单ctx.fillRect(..),请参阅http:// www。 wothke.ch/webgl_orbittrap/Orbittrap.htm

有趣的是,我的例子中的愚蠢的ctx.fillRect()实现实际上是基于ImageData的双缓冲方法的至less两倍。

至less在我的情况下,似乎内置的ctx.getImageData / ctx.putImageData其实是令人难以置信的SLOW。 (在基于ImageData的方法可能占据领先地位之前,知道需要触及的像素的百分比是很有趣的。)

结论:如果您需要优化性能,您必须剖析您的代码并根据您的发现采取行动。

这应该做的工作

 //get a reference to the canvas var ctx = $('#canvas')[0].getContext("2d"); //draw a dot ctx.beginPath(); ctx.arc(20, 20, 10, 0, Math.PI*2, true); ctx.closePath(); ctx.fill();