Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird HTML 5 Canvas Antialiasing

I've been playing with canvas element and discovered that when I attempt to draw NxN uniform solid-colored cells next to each other, in some width/height configurations, there are blurry white-ish lines between them.

For instance, this canvas is supposed to look black but contains some sort of grid which I conjecture to be a result of faulty antialiasing in the browser.

The canvas demonstrating the issue.

Suffice to say, this bug appears only in some configurations but I would like to get rid of it for good. Is there any way to circumvent this? Have you ever had problems with antialiasing in canvas?

I have made this fiddle which demonstrates the issue and allows you to play with the dimensions of the canvas and number of cells. It also contains the code I use to draw the cells, so that you can inspect it and tell me if I'm doing anything wrong.

var ctx = canvas.getContext('2d');  
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
for (var i = 0; i < numberOfCells; ++i) {
    for (var j = 0; j < numberOfCells; ++j) {
    ctx.fillStyle = '#000';
    ctx.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
  }
}

Thanks in advance,

Petr.

like image 757
Petr Mánek Avatar asked Dec 17 '15 11:12

Petr Mánek


3 Answers

jsFiddle : https://jsfiddle.net/ngxjnywz/2/

snippet of javascript

var cellWidth = Math.ceil(canvasWidth / numberOfCells);
var cellHeight = Math.ceil(canvasHeight / numberOfCells);

Depending on the width, height and your numberOfCells you are sometimes getting a... lets say 4.2 which is 4, however this would be displayed wrong and will allow a 1 pixel blank line to appear. So all you need to do is use the Math.ceil function and this will cause your cellWidth and cellHeight to always be the higher number and you won't get blank lines anymore

like image 190
Canvas Avatar answered Oct 16 '22 18:10

Canvas


The best solution is to add a 0.5 pixel wide stroke around all the fills, using the same style as the fill and offsetting all drawing so that you render at the center of pixels rather than the top left.

If you add scaling or translation you will have to adjust the coordinates so that you still give the centers for your drawing coordinates.

In the end you can only reduce the artifacts but for many situations you will not be able to completely remove them.

This answer shows you how to remove the artifacts for an untransformed canvas. How to fill the gaps

like image 25
Blindman67 Avatar answered Oct 16 '22 17:10

Blindman67


After reading through and trying several approaches, I've decided to come up with my own. I've created another (virtual) canvas which had integer dimensions corresponding to the number of cells in the grid.

After drawing all the cells in there, I call context.drawImage() on the main canvas and pass the virtual canvas as an argument along with offset and scale parameters to make it fit rest of my drawing. Assuming that the browser would scale the virtual canvas's image as a whole (and not as individual cells), I was hoping to get rid of the unwanted separator lines.

In spite of my efforts, the lines are still there. Any suggestions?

Here's the fiddle demonstrating my technique: https://jsfiddle.net/ngxjnywz/5/

like image 28
Petr Mánek Avatar answered Oct 16 '22 16:10

Petr Mánek