2017-09-22 59 views
0

我正在使用HTML5画布元素,我正在处理一个项目,同时呈现一堆东西,我遇到了一个非常奇怪的工件,我想知道如果有人曾经见过。基本上,在这个特定的场景中(这是我见过的唯一产生这种行为的情况),我恰好在平移/缩放应用程序,并注意到在画布的一部分上出现了一种奇怪的渲染效果。经进一步检查,我能够重现一个非常简单的例子效果:奇怪的HTML5画布关闭路径渲染神器

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

看起来,因为如果去掉调用context.closePath()可能与调用canvas.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)。我已经做了一些广泛的搜索,试图找到这个问题(或者类似的东西),但是到目前为止已经空了。

任何洞察什么可能会导致此(或正确的方式来报告这个问题,如果共识是它是由一些浏览器错误引起)将不胜感激。

+0

这是由两个线段之间的一个非常小的角度引起的斜角伪影,并且可以通过将'context'的'lineJoin'属性设置为''round''或''斜角''来消除。默认的'lineJoin'是''miter'',它有一个限制。通过“miterLimit”属性设置斜接限制,虽然它并不总是能够消除伪像。由于从双打(64位浮点JS数)转换为浮点(GPU使用32Bit)时得到的舍入误差,您的问题会加剧。给定的答案将解决您的问题,并值得一票。 – Blindman67

+0

@ blindman67只是想报告,也'斜角'失败在我的Firefox;看着alpha混合的神器三角形,我被说服了,这完全是一个着色器问题,而不是定向逻辑中的一个bug。 –

+0

@ Blindman67在将'lineJoin'设置为''bevel''时,我也看到失败,但是,当将'lineJoin'设置为'“round”'时,问题似乎得到解决。 – Sanuden

回答

3

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

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

据我所知,似乎通过设置lineJoin解决了“圆”或减少线宽...无论如何,似乎呈现错误给我...只是我的两分钱:)