Drawing dots on HTML5 canvas

Drawing a line on HTML5 canvas is quite simple using the context.moveTo() and context.lineTo() functions.

I'm not quite sure if it is possible to draw a point, that is, the color of one pixel. The lineTo function will not draw a single pixel line (obviously).

Is there any way to do this?

+83
html5 canvas
Oct 18 '11 at 19:24
source share
6 answers

For performance reasons, do not draw a circle if you can avoid it. Just draw a rectangle wide and high:

 ctx.fillRect(10,10,1,1); // fill in the pixel at (10,10) 
+99
Oct 18 '11 at 20:29
source share

If you plan to draw a lot of pixels, it’s much more efficient to use image data on the canvas to draw pixels.

 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 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 how you update the canvas, so that your // // modification are taken in consideration // function updateCanvas() { ctx.putImageData(canvasData, 0, 0); } 

How can you use it 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/

+122
Nov 28 2018-11-11T00:
source share

It seems strange, but nevertheless HTML5 supports drawing lines, circles, rectangles and many other basic shapes, it has nothing suitable for drawing a basic point. The only way to do this is to simulate a point with what you have.

So basically there are 3 possible solutions:

  • line drawing point
  • drawing point as a polygon
  • circle drawing point

Each of them has its 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 reaching the southeast direction, and if this is the edge, a problem may arise. But you can also draw in any other direction.




Rectangle

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

or faster using fillRect, because the render engine will just fill one pixel.

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



a circle

One of the problems with circles is that it’s more difficult for the engine to display them.

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

same idea as a rectangle that you can achieve with a fill.

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

Problems with all of these solutions:

  • It is hard to keep track of all the points that you are about 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 a filled rectangle. You can see jsperf here with benchmarks

+27
Oct 29 '13 at
source share

In my Firefox this trick works:

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

A slight offset does not appear on the screen, but causes the rendering engine to actually draw a point.

+5
Mar 19 '14 at 8:53
source share

The above statement: “If you plan to draw a lot of pixels, it’s much more efficient to use the image data on the canvas to draw pixels”, it seems completely wrong - at least with Chrome 31.0.1650.57 m or depending on your definition of “many pixels”. I would prefer to comment directly on the corresponding entry, but unfortunately I still don't have enough stackoverflow points:

I think I draw "a lot of pixels," and so I carefully followed the appropriate tips first. Later, I changed my implementation to a simple ctx.fillRect (..) for each point drawn, see http://www.wothke.ch/webgl_orbittrap/Orbittrap.htm

Interestingly, the stupid implementation of ctx.fillRect () in my example is actually at least twice as fast as the double-buffering method based on ImageData.

At least for my scenario, it seems that the built-in ctx.getImageData / ctx.putImageData is actually incredibly slow. (It would be interesting to know the percentage of pixels that need to be touched before the ImageData-based approach can take the lead.)

Conclusion: if you need to optimize performance, you need to profile your code and act on YOUR results.

+4
Jun 24 '14 at 17:02
source share

This should do the job.

 //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(); 
+3
Sep 21
source share



All Articles