javascript - 奇怪的 HTML5 Canvas closePath 渲染神器

标签 javascript canvas rendering

我在一个正在开发的项目中使用 HTML5 Canvas 元素,在渲染一堆东西时,我遇到了一个非常奇怪的工件,我想知道是否有人以前见过它。基本上,在这个特定的场景中(这是我见过的唯一会产生这种行为的情况),我碰巧在我的应用程序中进行平移/缩放,并注意到 Canvas 的一部分出现了非常奇怪的渲染效果。经过进一步检查,我能够在一个非常简单的示例中重现效果:

Strange HTML5 Canvas Rendering Artifact

在这种情况下,我有一条路径(其坐标不会改变),从第一个屏幕截图到第二个屏幕截图的所有变化都是所应用的变换矩阵(变化量非常小)。

您可以访问我用来生成这些屏幕截图的 JSFiddle https://jsfiddle.net/ynsv66g8/这是相关的渲染代码:

// 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();

它看起来与对 canvas.closePath() 的调用有关,因为如果您删除对 context.closePath() 的调用并将其替换为:

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

(从而手动“关闭”路径)一切正常(当然,这确实不能解决我的特定问题,因为我依赖多个闭合路径来应用填充规则)。

另一个可以解决问题的有趣更改是反转 path 数组(即,通过添加对 path.reverse() 的调用)在其定义之后)。

总而言之,所有这些似乎都增加了某种与路径特征相关的浏览器渲染错误,特别是因为在我的 Mac 上,Chrome (v61.0.3163.91) 和 Firefox 都出现了该问题(v55.0.3) 但不是 Safari (v11)。我已经进行了一些广泛的搜索,试图找到这个问题(或类似的问题),但到目前为止还是一无所获。

任何对可能导致此问题的原因的深入了解(或者如果一致认为该问题是由某些浏览器错误引起的,则报告此问题的正确方法)将不胜感激。

最佳答案

这似乎是一个线斜接问题;也就是说,当宽度相对于线段大小/方向太大时,渲染器无法正确连接线。

这似乎不受路径关闭的影响(我可以使用开放路径重现工件);请注意,手动关闭路径与 closePath() 不同,因为在前一种情况下不执行行连接。

据我所知,这似乎是通过将 lineJoin 设置为“圆形”或减小线宽来解决的......无论如何,对我来说似乎是一个渲染器错误......只是我的两分钱:)

关于javascript - 奇怪的 HTML5 Canvas closePath 渲染神器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46368209/

相关文章:

jquery - iOS 7 Safari jquery text() 没有被渲染

java - Android Canvas渲染

javascript - Google map 自动完成 - 最多 3 个字符类型

javascript - 如何在填充有 Json 数据的 knockout View 模型中定义函数

javascript - 更改菜单图像

javascript - 如何链接 P5.js 设置并使用 html canvas 进行绘制?

javascript - 嘿,我想用canvas和js制作这个小程序来检测圆圈之间的碰撞

java - 绘画 Canvas 和 System.out.println() 不起作用

c++ - OpenGL 3.2 为什么我会收到 glTexStorage3D 的 INVALID_ENUM 错误?

javascript - 如何用标签包裹多个 HTML 字符串?