Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Curious bug (?) of HTML5 canvas rendering rectangles

I am using HTML5 canvas to pre-render sprites and have come across some weird behavior which looks like a rendering bug. The following minimal example produces it:

var CT = document.getElementById("myCanvas").getContext("2d");
CT.scale(24, 24);
CT.translate(1.0717, 0.1);
CT.rect(0.2, 0.35, 0.4, 0.1);
CT.rect(-0.05, -0.05, 0.1, 1);
CT.translate(0.4, 0);
CT.rect(-0.05, -0.05, 0.5, 1);
CT.fill();
<canvas id="myCanvas" width="50" height="30" style="border:1px solid #d3d3d3;"></canvas>

Looking at the resulting image I notice that the horizontal bar interferes with the left side vertical one, although it does not touch it. Changing the geometry (e.g. removing the right-side vertical bar), changes the artifacts in an (as far as I can see) unpredictable way.

enter image description here

Has anyone of you come across this issue? What could cause it and how to avoid it? This is annoying me more than it should. The behavior occurs in different browsers (I tested on IE11 and Firefox Quantum).

If it's not clear look at the left most column of pixels on the left most rectangle. The pixels pointed at the red arrow are darker than the pixels pointed at by the blue arrow even though the other 2 rectangles on the right seem like they should have absolutely no influence on the rectangle on the left.

enter image description here

like image 688
Florian Käferböck Avatar asked Dec 01 '17 13:12

Florian Käferböck


1 Answers

I managed to repo the issue in Edge but not Firefox 57.0.1 or Chrome 62. This might not be the fastest solution but it did fix the problem in Edge which is to rasterize each rectangle on it's own by calling CT.fill followed by CT.beginPath after each rectangle.

var CT = document.getElementById("myCanvas").getContext("2d");
CT.scale(24, 24);
CT.translate(1.0717, 0.1);
CT.rect(0.2, 0.35, 0.4, 0.1);
CT.fill();
CT.beginPath();
CT.rect(-0.05, -0.05, 0.1, 1);
CT.fill();
CT.beginPath();
CT.translate(0.4, 0);
CT.rect(-0.05, -0.05, 0.5, 1);
CT.fill();
<canvas id="myCanvas" width="50" height="30" style="border:1px solid #d3d3d3;"></canvas>

Honestly I'd file a bug. While I know the canvas spec is somewhat lenient it's hard to imagine this particular issue is spec compliant. (though it may be)

like image 137
gman Avatar answered Oct 01 '22 22:10

gman