Canvas 如何避免画布中填充区域之间的接缝?

Canvas 如何避免画布中填充区域之间的接缝?,canvas,graphics,Canvas,Graphics,当我在HTML5画布或类似系统(如Quartz或GDI+)中填充相邻区域时,我会在共享边缘上看到浅色接缝。下面是一个示例(代码如下): 我想我知道发生了什么,但没有解决办法。每个边都针对白色进行了抗锯齿处理,因此,不是橙色和蓝色的混合,而是橙色、蓝色和白色的混合 基本上,这个问题以前被问过,但讨论较少,没有很好的答案 一些涉及在接缝处绘制稍大一点的第一个形状或在接缝上绘制一条线的解决方案无法承受透明度或奇数形状组合等变化 禁用反走样可以避免支持反走样的API的接缝,但是,当然,所有边都是锯齿状

当我在HTML5画布或类似系统(如Quartz或GDI+)中填充相邻区域时,我会在共享边缘上看到浅色接缝。下面是一个示例(代码如下):

我想我知道发生了什么,但没有解决办法。每个边都针对白色进行了抗锯齿处理,因此,不是橙色和蓝色的混合,而是橙色、蓝色和白色的混合

基本上,这个问题以前被问过,但讨论较少,没有很好的答案

一些涉及在接缝处绘制稍大一点的第一个形状或在接缝上绘制一条线的解决方案无法承受透明度或奇数形状组合等变化

禁用反走样可以避免支持反走样的API的接缝,但是,当然,所有边都是锯齿状的

是否有一种方法可以向渲染器提供有关预期邻接的提示

<canvas id="myCanvas" width="300" height="150" /> <script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(100,0);  ctx.lineTo(115,150);  ctx.lineTo(300, 50);
ctx.closePath();  ctx.fillStyle="#885533";  ctx.fill();

ctx.beginPath();
ctx.moveTo(0,50);  ctx.lineTo(100,0);  ctx.lineTo(115,150);
ctx.closePath();  ctx.fillStyle="#335588";  ctx.fill();
</script>  </body>  </html>

var c=document.getElementById(“myCanvas”);
var ctx=c.getContext(“2d”);
ctx.beginPath();
ctx.moveTo(100,0);ctx.lineTo(115150);ctx.lineTo(300,50);
ctx.closePath();ctx.fillStyle=“#885533”;ctx.fill();
ctx.beginPath();
ctx.moveTo(0,50);ctx.lineTo(100,0);ctx.lineTo(115150);
ctx.closePath();ctx.fillStyle=“#335588”;ctx.fill();
是否有一种方法可以向渲染器提供有关预期邻接的提示

<canvas id="myCanvas" width="300" height="150" /> <script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(100,0);  ctx.lineTo(115,150);  ctx.lineTo(300, 50);
ctx.closePath();  ctx.fillStyle="#885533";  ctx.fill();

ctx.beginPath();
ctx.moveTo(0,50);  ctx.lineTo(100,0);  ctx.lineTo(115,150);
ctx.closePath();  ctx.fillStyle="#335588";  ctx.fill();
</script>  </body>  </html>
不幸的是,没有,抗锯齿/子像素在默认情况下处于启用状态,我们无法将其禁用

我可以想出一些方法来解决这个问题:

1) 使用注释中提到的技巧标记,并使用笔划n 挤出将导致它们重叠的多边形。您可以通过首先将
lineWidth
属性设置为
0.67
来减少影响

2) 通过将重叠线的坐标(通过添加到坐标或使用“平移”)平移一个像素来手动重叠。这将提供比1更好的结果,因为这只会挤出重叠区域中的多边形,而不是所有边上的多边形。然而,缺点是您需要手动计算每个重叠,这很快就会变得很痛苦,尤其是如果您还想为它们设置动画的话

3) 自己实现一个行填充算法(例如Bresenham)。这并不难,但会减慢绘图速度,如果您经常更新图形,这一点很明显。这样做的好处是,您可以准确地知道线条的绘制位置。缺点是,除非您也实现了消除混叠,并且以其自身的性价比实现,否则不会得到消除混叠

4) 1和3的组合,其中使用画布填充和透支重叠线,并使用Bresenham线算法


5) 使用一个大的屏幕外画布并按比例绘制所有内容。最后,将屏幕画布上的所有内容绘制为目标大小(或者使用CSS设置目标大小)。这将有助于隐藏间隙,还可以提供更清晰的线条,您也可以保留原始坐标,但它需要更多的像素处理和内存,因此速度较慢,但不会像3中的手动线条/填充方法那样慢。

如果您在透明画布上绘制,且形状不重叠,您只需设置
ctx.globalCompositeOperation=“打火机”


这意味着每个形状将使用而不是使用“典型”将其贡献与其像素的先前内容相结合。在本例中,这正是您想要的。

当前没有可用于画布路径图形的反别名控件。作为一种(p.i.t.a.)解决方法,您可以将不需要的笔划添加到绘图中。谢谢。我现在使用的是#1的变体,在填充之前,我只是沿着接缝划一条线。小心一点,透明效果看起来也不太差。