Reputation: 525
The following snippet draws vertical lines on a canvas (1px width). However, some lines appear to be wider than others, some are blurry, others are ok. In different posts i've read that one needs to substract 0.5 px or translate coordinates. It doesn't work in my case.
I've tried using translate by a factor odf 0.5, rounding coordinates and manually adding 0.5 (see the variations of the drawLine method). Nothing works
How can i get the vertical lines to be crisp and clean?
thank you
function doStuff() {
var cnv = document.getElementById("cnvs");
var ctx = cnv.getContext("2d");
var lw = 1;
ctx.lineWidth = lw;
var xMax = cnv.width;
var ygMax = cnv.height;
var iTranslate = 0.5; // (lw % 2) / 2;
ctx.translate(iTranslate, iTranslate);
deltaX = 12;
for (var x = deltaX; x < xMax; x += deltaX) {
drawLine(ctx, x, ygMax, x, 0);
}
}
function drawLine(ctx, x0, y0, xf, yf) {
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(xf, yf);
ctx.stroke();
ctx.closePath();
}
function drawLine2(ctx, x0, y0, xf, yf) {
ctx.beginPath();
ctx.moveTo(Math.round(x0), y0);
ctx.lineTo(Math.round(xf), yf);
ctx.stroke();
ctx.closePath();
}
function drawLine3(ctx, x0, y0, xf, yf) {
ctx.beginPath();
ctx.moveTo(x0 + 0.5, y0);
ctx.lineTo(xf + 0.5, yf);
ctx.stroke();
ctx.closePath();
}
doStuff();
<canvas id="cnvs" width="200" height="100"></canvas>
Upvotes: 0
Views: 995
Reputation:
The lines shown in the code are as crisp as they can get. Lines cannot be thinner than one pixel (this is what I get from your code in Firefox and Opera):
You can from this point only give the illusion of them being thinner by reducing the blackness. For example, if you stroke with mid-gray (#777) color they will appear like this:
But they are the exact same size.
This illusion is the same that you would get if you used a line width of 0.5 or used a double sized canvas and reduced it to half using CSS (in those cases due to resampling / interpolation).
Addendum: If the lines in the images above still look uneven there is the possibility that your monitor settings aren't optimal, ie. the resolution in use does not match the physical pixels of the screen. Check that the system settings are using the recommended resolution as any other will force interpolation/resampling at system/hardware level and no matter what you do in canvas won't help.
function doStuff() {
var cnv = document.getElementById("cnvs");
var ctx = cnv.getContext("2d");
var lw = 1;
ctx.lineWidth = lw;
var xMax = cnv.width;
var ygMax = cnv.height;
var iTranslate = 0.5; // (lw % 2) / 2;
ctx.translate(iTranslate, iTranslate);
deltaX = 12;
ctx.strokeStyle = "#777";
for (var x = deltaX; x < xMax; x += deltaX) {
drawLine(ctx, x, ygMax, x, 0);
}
}
function drawLine(ctx, x0, y0, xf, yf) {
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(xf, yf);
ctx.stroke();
}
doStuff();
<canvas id="cnvs" width="200" height="100"></canvas>
Upvotes: 1
Reputation: 448
It'd be better to round your coordinates to an integer rather than changing the values by 0.5 every time - for example, x = Math.floor(x)
(to round down automatically) or x = Math.round(x)
(for more traditional rounding). Coordinates can be off by intervals other than 0.5, which would make them render fuzzily as you're experiencing.
Upvotes: 0