Drawing a dot on HTML5 canvas

For performance reasons, don't draw a circle if you can avoid it. Just draw a rectangle with a width and height of one:

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

If you are planning to draw a lot of pixel, it's a lot more efficient to use the image data of the canvas to do pixel drawing.

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

Then, you can use it in this way :

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

For more information, you can take a look at this Mozilla blog post : http://hacks.mozilla.org/2009/06/pushing-pixels-with-canvas/


It seems strange, but nonetheless HTML5 supports drawing lines, circles, rectangles and many other basic shapes, it does not have anything suitable for drawing the basic point. The only way to do so is to simulate a point with whatever you have.

So basically there are 3 possible solutions:

  • draw point as a line
  • draw point as a polygon
  • draw point as a circle

Each of them has their drawbacks.


Line

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

Keep in mind that we are drawing to South-East direction, and if this is the edge, there can be a problem. But you can also draw in any other direction.


Rectangle

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

or in a faster way using fillRect because render engine will just fill one pixel.

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

Circle

One of the problems with circles is that it is harder for an engine to render them

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

the same idea as with rectangle you can achieve with fill.

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

Problems with all these solutions:

  • it is hard to keep track of all the points you are going to draw.
  • when you zoom in, it looks ugly

If you are wondering, what is the best way to draw a point, I would go with filled rectangle. You can see my jsperf here with comparison tests

Tags:

Html

Canvas