HTML5画布:组合区域周围的单笔画

时间:2013-07-31 18:48:37

标签: html5 canvas html5-canvas

HTML5画布:我正在寻找一种在组合路径上绘制单个笔划的方法。

例如,如果我有两个重叠的圆圈,我不希望有两个重叠的圆形笔划,但是在两个圆圈的组合区域周围只有一个笔划。

有机会吗?

2 个答案:

答案 0 :(得分:2)

可以使用globalCompositeOperation来完成。有各种方法可以自己绘制形状,但这里有一种方法可以实现这一点(对于演示中的两个矩形圆圈):

enter image description here

  • 第1步:设置普通画布
  • 第2步:设置离屏画布

更新不确定我怎么会错过显而易见的,但你当然可以首先抚摸圈子,然后用复合模式和填充打一整个 - 多更快(我猜想当我想出偏移重绘时,我的脑海中有了图像)。

离屏画布的原因是如果你在主画布上已经有了背景。除非我们打洞,否则这将被删除。如果没有什么,那么将它绘制到单个画布上没有问题 - 更新的代码:

/// some regions
var rect = [ [20, 20, 200, 200], [100, 100, 200,200] ],

/// ox = off-screen context
ox.strokeStyle = '#fff';
ox.lineWidth = 3 * 2; /// x2 as half will be gone when we punch hole

/// stroke outlines
for(; r = rect[i]; i++) {
    o = r[2] * 0.5;
    ox.beginPath();
    ox.arc(r[0] + o, r[1] + o, o, 0, 2 * Math.PI);
    ox.stroke();
}

/// punch hole with composite mode and fill
ox.globalCompositeOperation = 'destination-out';    
for(i = 0; r = rect[i]; i++) {
    o = r[2] * 0.5;
    ox.beginPath();
    ox.arc(r[0] + o, r[1] + o, o, 0, 2 * Math.PI);
    ox.fill();
}

/// draw result to main canvas
/// ctx = main context, ocanvas = off-screen canvas
ctx.drawImage(ocanvas, 0, 0);

<强> (Animated) online demo using this optimized version

我将保留旧代码,因为它可以用于无法描边的图像 -

现在将填充形状绘制到离屏画布上。绘制您希望轮廓所在的颜色。

/// some regions
var rect = [ [20, 20, 200, 200], [100, 100, 200,200] ],

/// ox = off-screen canvas
ox.fillStyle = '#fff';

/// draw the array with circes
for(; r = rect[i]; i++) {
    var o = r[2] * 0.5;
    ox.beginPath(); //use this here - arcs are currently buggy
    ox.arc(r[0] + o, r[1] + o, o, 0, 2 * Math.PI);
    ox.fill(); //.. and here
}

现在将形状的缓存图像绘制回主画布。必须在每个方向上稍微偏移绘制形状 - 此步骤将创建轮廓:

/// ctx = main context, ocanvas = off-screen canvas
ctx.drawImage(ocanvas, -1, -1);
ctx.drawImage(ocanvas, 1, -1);
ctx.drawImage(ocanvas, 1, -1);
ctx.drawImage(ocanvas, 1, 1);
ctx.drawImage(ocanvas, -1, 1);
ctx.drawImage(ocanvas, 1, 1);
ctx.drawImage(ocanvas, -1, -1);
ctx.drawImage(ocanvas, -1, 1);

最后,我们在填充的形状中打出一个“洞”,使其使用globalCompositeOperation +在0偏移位置的最终绘制时使用轮廓透明:

ctx.globalCompositeOperation = 'destination-out';
ctx.drawImage(ocanvas, 0, 0);

ONLINE DEMO

要使边框更粗,只需在将形状绘制到主画布时增加偏移量。

答案 1 :(得分:0)

这是我目前的解决方案。不需要第二个画布,更容易实现。它仍然使用Ken的想法来使用globalCompositeOperation

context.lineWidth = 2;
context.stroke();
var prev = context.globalCompositeOperation;
context.globalCompositeOperation = "destination-out";
context.fill();
context.globalCompositeOperation = prev;