简体   繁体   中英

Strange HTML5 Canvas closePath rendering artifact

I'm using HTML5 Canvas elements in a project I'm working on and while rendering a bunch of stuff I ran into a really strange artifact that I'm wondering if anyone has ever seen before. Basically, in this particular scenario (this is the only case I've seen that produces this behavior), I happened to be panning/zooming in my application and noticed a very bizarre rendering effect on part of the canvas. Upon further inspection, I was able to reproduce the effect in a very simplistic example:

奇怪的HTML5画布渲染工件

In this case, I have a path (whose coordinates don't change) and all that is changing from the first screenshot to the second is the applied transformation matrix (by a very small amount).

You can access the JSFiddle I used to generate these screenshots at https://jsfiddle.net/ynsv66g8/ and here is the relevant rendering code:

// Clear context
context.setTransform(1, 0, 0, 1, 0, 0);
context.fillStyle = "#000000";
context.fillRect(0, 0, 500, 500);

if (showArtifact) { // This transformation causes the artifact
  context.transform(0.42494658722537976, 0, 0, -0.42494658722537976, 243.95776291868646, 373.14630356628857);
} else { // This transformation does not
  context.transform(0.4175650109545749, 0, 0, -0.4175650109545749, 243.70987992043368, 371.06797574381795);
}

// Draw path
context.lineWidth = 3.488963446543301;
context.strokeStyle = 'red';
context.beginPath();
var p = path[0];
context.moveTo(p[0], p[1]);
for (var i = 1; i < path.length; ++i) {
  p = path[i];
  context.lineTo(p[0], p[1]);
}
context.closePath();
context.stroke();

It looks to be related to the call to canvas.closePath() because if you remove the call to context.closePath() and replace it with:

p = path[0];
context.lineTo(p[0], p[1]);

(thus manually "closing" the path) everything works properly (granted, this really doesn't fix my particular issue because I rely on multiple closed paths to apply filling rules).

Another interesting change that can be made that makes the issue go away is to reverse the path array (ie, by adding a call to path.reverse() right after its definition).

Together, all of this seems to be adding up to some kind of browser rendering bug related to the characteristics of the path, especially since, on my Mac, the issue occurs in both Chrome (v61.0.3163.91) and Firefox (v55.0.3) but not Safari (v11). I've done some extensive searching to try to find this issue (or something similar), but thus far have come up empty.

Any insight into what might be causing this (or the proper way to go about reporting this issue if the consensus is that it is caused by some browser bug) would be greatly appreciated.

it seems a line mitering problem; that is, the renderer fails to correctly join lines when the width is too big relative to the segment size/orientation.

This seems not influenced by path closing ( I can reproduce the artifact with the open path ); note that manually closing the path is not the same as a closePath(), because no line join is performed in the former case.

As far as I can tell, it seems solved by setting lineJoin to 'round' or reducing the line width ... anyway, seems a renderer bug to me ... just my two cents :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM