在HTML5画布上绘制一个点

时间:2011-10-18 19:24:10

标签: html5 canvas

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

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

有没有办法做到这一点?

6 个答案:

答案 0 :(得分:141)

如果您打算绘制大量像素,使用画布的图像数据进行像素绘制会更有效率。

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/

答案 1 :(得分:125)

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

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

答案 2 :(得分:36)

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

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

  • 绘制点作为一行
  • 将点绘制为多边形
  • 画圆点

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


订单

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

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

  • 很难跟踪你要绘制的所有点。
  • 放大时,看起来很难看

如果您想知道什么是绘制点的最佳方式,我会选择填充矩形。您可以看到我的jsperf here with comparison tests

答案 3 :(得分:6)

在我的Firefox中,这个技巧有效:

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

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

答案 4 :(得分:4)

上述说法“如果你计划绘制大量像素,那么使用画布的图像数据进行像素绘制会更加高效”似乎是非常错误的 - 至少Chrome 31.0.1650.57 m或取决于你对“很多像素”的定义。我本来希望直接评论相应的帖子 - 但不幸的是我还没有足够的stackoverflow点:

我认为我正在绘制“很多像素”,因此我首先遵循相应的建议以获得良好的衡量标准我后来将我的实现更改为每个绘制点的简单ctx.fillRect(..),请参阅{{3 }}

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

至少在我的场景中,似乎内置的ctx.getImageData / ctx.putImageData实际上是令人难以置信的缓慢。 (在基于ImageData的方法可能起带头作用之前,知道需要触摸的像素百分比会很有趣。)

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

答案 5 :(得分:3)

这应该做的工作

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