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

时间:2013-10-11 13:55:00

标签: canvas graphics

当我填充HTML5 Canvas中的相邻区域或Quartz或GDI +等类似系统时,我在共享边缘看到浅色接缝。这是一个例子,(下面的代码):

enter image description here

我想我明白发生了什么,但没有修复。每条边都是白色的抗锯齿,所以不是混合橙色和蓝色,而是混合了橙色,蓝色和白色。

基本上same question之前已被问过,但讨论较少且没有好的答案。

某些解决方法涉及在接缝处绘制稍大一点的第一个形状或在接缝上画一条线,但不能保持透明度或奇怪形状组合等变化。

关闭抗锯齿避免了支持它的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>

2 个答案:

答案 0 :(得分:1)

  

有没有办法向渲染器提供有关预期邻接的提示?

不幸的是,没有,抗锯齿/子像素化默认打开,我们无法将其关闭。

我可以通过一些方法来解决这个问题:

1)在评论中使用markE提及的技术并使用笔画n 挤出将导致它们重叠的多边形。您可以先将lineWidth属性设置为0.67来减少影响。

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

3)自己实施一条线和填充算法(例如Bresenham)。这不是那么难,但它会减慢绘图速度,如果你经常更新图形,那就明显了。好处是您可以确切地知道线条的绘制位置。缺点是你没有消除锯齿,除非你也以自己的性价比实现这一点。

4)1和3的组合,你使用画布'填充并用Bresenham线算法覆盖重叠线。

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

答案 1 :(得分:1)

如果您在透明的画布上绘画并且形状不重叠,则只需设置ctx.globalCompositeOperation = "lighter"

your example with globalCompositeOperation = "lighter"

这意味着每个形状都将使用simple addition而不是典型的alpha blending将其贡献与其像素的先前内容结合起来。在这种情况下,这正是您想要的。