在HTML5画布上绘制点[重复]

问题描述 投票:107回答:6

此问题已经在这里有了答案:

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

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

是否有执行此操作的方法?

html5 canvas
6个回答
131
投票

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

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

144
投票

如果您打算绘制很多像素,则使用画布的图像数据进行像素绘制会效率更高。

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/


39
投票

似乎很奇怪,但是HTML5仍支持绘制线条,圆形,矩形和许多其他基本形状,它没有适合绘制基本点的任何内容。这样做的唯一方法是使用您拥有的任何东西来模拟一个点。

因此,基本上有3种可能的解决方案:

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

每个都有其缺点。


Line

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


6
投票

在我的Firefox中,此技巧有效:

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

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


6
投票

以上说法“如果您打算绘制很多像素,则使用画布的图像数据进行像素绘制会更有效率”,似乎是完全错误的-至少对于Chrome 31.0.1650.57 m或取决于您对“像素”的定义。我本来希望直接对相应的帖子发表评论-但不幸的是我还没有足够的stackoverflow点:

[我认为我正在绘制“很多像素”,因此我首先按照各自的建议采取了很好的措施,后来我为每个绘制的点将实现更改为简单的ctx.fillRect(..),请参见http://www.wothke.ch/webgl_orbittrap/Orbittrap.htm] >

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

至少对于我的情况,似乎内置的ctx.getImageData / ctx.putImageData确实慢得令人难以置信。 (了解基于ImageData的方法可能需要领先的像素需要触摸的百分比会很有趣。)

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


3
投票

这应该做的工作

© www.soinside.com 2019 - 2024. All rights reserved.