Reputation: 4643
Say I have the next code to draw a grid using canvas:
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
rows = 10,
cols = 10,
size = canvas.getAttribute("width") / rows;
drawGrid();
function drawGrid() {
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
ctx.strokeStyle ='rgba(242, 198, 65, 0.1)';
ctx.strokeRect(i * size, j * size, size, size);
ctx.fillStyle = 'rgb(38,38,38)';
ctx.fillRect(i * size, j * size, size, size);
}
}
}
You can view the result here
My question is why the grid appears thicker if I comment the line ctx.fillRect(i * size, j * size, size, size);
EDIT
And how can I get the same result without using fillRect
?
Upvotes: 2
Views: 628
Reputation: 63812
your strokes are rendered on half-pixels, which causes them to blur across two pixels. Your fills are covering up part of that, making them look like half pixels again.
The simple solution is to offset the drawing by 0.5, 0.5
in order to draw on whole pixels. For more on this see the section of http://diveintohtml5.info/canvas.html that starts:
Q: Why did you start x and y at 0.5? Why not 0?
Anyway, you shouldn't be using rects for making a grid, you should just be using lines, and you should only ever have to stroke once, at the end, when the grid is done. Doing so ensures that your semi-transparent grid does not have thicker spots at the intersection points of the grid lines.
Here's an example:
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
rows = 10,
cols = 10,
size = canvas.width / rows,
width = canvas.width,
height = canvas.height;
drawGrid();
function drawGrid() {
// An odd-sized lineWidth means we should translate to draw on whole pixels
ctx.translate(0.5, 0.5);
for (var i = 1; i < rows; i++) {
ctx.moveTo(0, i * size);
ctx.lineTo(width, i * size);
}
for (var j = 1; j < cols; j++) {
ctx.moveTo(j * size, 0);
ctx.lineTo(j * size, height);
}
// translate back:
ctx.translate(-0.5, -0.5);
// setting stroke style and stroking just once
ctx.strokeStyle = 'rgba(242, 198, 65, 0.1)';
ctx.stroke();
}
fiddle: http://jsfiddle.net/tZqZv/4/
Upvotes: 3
Reputation: 3498
The rendered strokes are straddling pixel borders. This is manifest in the appearance of what looks like an anti-aliasing effect, and therefore when the fill is not applied and not overlapping the pixel borders, the line appears thicker. If we translate by 0.5, then we do not straddle the pixel borders and observe no difference in the line thickness whether the fill is applied or not. Here's an example.
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
rows = 10,
cols = 10,
size = canvas.getAttribute("width") / rows - 5;
drawGrid();
function drawGrid() {
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
ctx.strokeStyle ='rgba(0, 0, 0, 1)';
ctx.strokeRect(i * size + 0.5, j * size + 0.5, size, size);
ctx.fillStyle = 'rgb(38,128,128)';
//ctx.fillRect(i * size + 0.5, j * size + 0.5, size, size);
}
}
}
Here's a decent reference to the effect.
Upvotes: 2
Reputation: 45135
Because your fillRect
is overlapping with the borders drawn by strokeRect
.
Upvotes: 1