在 HTML5画布上画一个点

使用 context.moveTo()context.lineTo()函数在 HTML5画布上绘制线条非常简单。

我不太确定是否可以画一个点,也就是一个像素的颜色。LineTo 函数不会绘制单个像素线(很明显)。

有什么方法可以做到这一点吗?

184496 次浏览

出于性能考虑,如果可以避免,不要画圆。只要画一个宽度和高度为1的矩形:

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

如果您计划绘制大量像素,那么使用画布的图像数据进行像素绘制会更加有效。

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/

这个应该可以了

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

这似乎很奇怪,但尽管如此,HTML5支持绘制线条、圆、矩形和许多其他基本形状,它没有任何东西适合绘制基本点。这样做的唯一方法是用你所拥有的任何东西模拟一个点。

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

  • 作为直线画点
  • 作为多边形的绘制点
  • 画圆点

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


台词

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

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

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

所有这些解决方案的问题:

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

如果你想知道,什么是 得出结论的最好方法,我会用填充矩形。你可以看到我的 Jsperf 在这里进行比较测试

在我的火狐浏览器中,这个技巧很管用:

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

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

上面所说的“如果你打算画很多像素,那么使用画布上的图像数据来画像素会更有效率”似乎是完全错误的——至少在 Chrome 31.0.1650.57 m 上是这样,或者取决于你对“很多像素”的定义。我更愿意直接对相应的帖子进行评论——但不幸的是,我还没有足够的堆栈溢出点:

我认为我正在绘制“大量像素”,因此我首先遵循了各自的建议,以便采取适当措施,后来我将实现更改为一个简单的 ctx.fill Rect (。.)对于每个绘制点,请参阅 http://www.wothke.ch/webgl_orbittrap/Orbittrap.htm

有趣的是,我的示例中愚蠢的 ctx.fill Rect ()实现的速度实际上至少是基于 ImageData 的双缓冲方法的两倍。

至少在我的场景中,内置的 ctx.getImageData/ctx.putImageData 实际上是难以置信的慢。(了解在基于 ImageData 的方法可能起主导作用之前需要触摸的像素百分比是很有趣的。.)

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