Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 Canvas and Line Width

Tags:

I'm drawing line graphs on a canvas. The lines draw fine. The graph is scaled, every segment is drawn, color are ok, etc. My only problem is visually the line width varies. It's almost like the nib of a caligraphy pen. If the stroke is upward the line is thin, if the stroke is horizontal, the line is thicker.

My line thickness is constant, and my strokeStyle is set to black. I don't see any other properties of the canvas that affect such a varying line width but there must be.

like image 677
simusid Avatar asked Sep 23 '11 14:09

simusid


People also ask

How do I change the width of a line in HTML canvas?

The HTML canvas lineWidth property is used to set or return the width of the line (thickness of the line). The width of the line is set in terms of pixels. The default value of this property is 1.

How do you change the thickness of a line on a canvas?

You need to start a new path with beginPath() for each line, set lineWidth and then stroke() the line for each. Here is an adjustment (fiddle below): var context = canvas. getContext("2d"); context.

How do you draw a thin line on a canvas?

strokeStyle = 'white'; ctx. lineWidth = 0.1; ctx. stroke();


2 Answers

Javascript:

var badCanvas = document.getElementById("badCanvas"),     goodCanvas = document.getElementById("goodCanvas"),     bCtx = badCanvas.getContext("2d"),     gCtx = goodCanvas.getContext("2d");  badCanvas.width = goodCanvas.width = badCanvas.height = goodCanvas.height = 300;  // Line example where the lines are blurry weird ect. // Horizontal bCtx.beginPath(); bCtx.moveTo(10,10); bCtx.lineTo(200,10); bCtx.stroke(); //Verticle bCtx.beginPath(); bCtx.moveTo(30,30); bCtx.lineTo(30,200); bCtx.stroke();  // Proper way to draw them so they are "clear" //Horizontal gCtx.beginPath(); gCtx.moveTo(10.5,10.5); gCtx.lineTo(200.5,10.5); gCtx.stroke(); //Verticle gCtx.beginPath(); gCtx.moveTo(30.5,30); gCtx.lineTo(30.5,200); gCtx.stroke();   // Change the line width bCtx.lineWidth = 4; gCtx.lineWidth = 4;   // Line example where the lines are blurry weird ect. // Horizontal bCtx.beginPath();   bCtx.moveTo(10,20.5); bCtx.lineTo(200,20.5); bCtx.stroke(); //Verticle bCtx.beginPath() bCtx.moveTo(50.5,30); bCtx.lineTo(50.5,200); bCtx.stroke();  // Proper way to draw them so they are "clear" //Horizontal gCtx.beginPath(); gCtx.moveTo(10,20); gCtx.lineTo(200,20); gCtx.stroke(); //Verticle gCtx.beginPath(); gCtx.moveTo(50,30); gCtx.lineTo(50,200); gCtx.stroke(); 

HTML:

<h2>BadCanvas</h2> <canvas id="badCanvas"></canvas> <h2>Good Canvas</h2> <canvas id="goodCanvas"></canvas> 

CSS:

canvas{border:1px solid  blue;} 

Live Demo

My live demo basically just recreates what the MDN says. For even stroke widths you can use integers for coordinates, for odd stroke widths you want to use .5 to get crisp lines that fill the pixels correctly.

MDN Image

From MDN Article

If you consider a path from (3,1) to (3,5) with a line thickness of 1.0, you end up with the situation in the second image. The actual area to be filled (dark blue) only extends halfway into the pixels on either side of the path. An approximation of this has to be rendered, which means that those pixels being only partially shaded, and results in the entire area (the light blue and dark blue) being filled in with a color only half as dark as the actual stroke color. This is what happens with the 1.0 width line in the previous example code.

To fix this, you have to be very precise in your path creation. Knowing that a 1.0 width line will extend half a unit to either side of the path, creating the path from (3.5,1) to (3.5,5) results in the situation in the third image — the 1.0 line width ends up completely and precisely filling a single pixel vertical line.

like image 94
Loktar Avatar answered Sep 20 '22 23:09

Loktar


If linewidth is an odd number, just add 0.5 to x or y.

like image 34
hzqij1978 Avatar answered Sep 18 '22 23:09

hzqij1978