首页 文章

在HTML5画布上画一个点[重复]

提问于
浏览
97

这个问题在这里已有答案:

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

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

有没有办法做到这一点?

6 回答

  • 6

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

    我认为我正在绘制"a lot of pixels"因此我首先遵循相应的建议以获得良好的衡量标准我后来将我的实现更改为每个绘制点的简单ctx.fillRect(..),请参阅http://www.wothke.ch/webgl_orbittrap/Orbittrap.htm

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

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

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

  • 3

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

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

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

    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/

  • 34

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

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

    • 绘制点作为一条线

    • 绘制点作为多边形

    • 画圆点

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


    Line

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

    请记住,我们正在向东南方向前进,如果这是边缘,则可能存在问题 . 但你也可以在任何其他方向画画 .


    Rectangle

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

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

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

    Circle

    圆圈的一个问题是引擎更难渲染它们

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

    Problems with all these solutions:

    • 很难跟踪你要绘制的所有点 .

    • 当你放大时,它看起来很难看

    如果你想知道什么是 the best way to draw a point ,我会选择填充矩形 . 你可以看到我jsperf here with comparison tests

  • 4

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

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

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

  • 136

    这应该做的工作

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

相关问题