HTML5 画布:我正在寻找一种在组合路径周围绘制单个笔划的方法。
例如,如果我有两个重叠的圆圈,我不想有两个重叠的圆圈笔画,而是在两个圆圈的组合区域周围有一个笔画..
有机会吗?
HTML5 画布:我正在寻找一种在组合路径周围绘制单个笔划的方法。
例如,如果我有两个重叠的圆圈,我不想有两个重叠的圆圈笔画,而是在两个圆圈的组合区域周围有一个笔画..
有机会吗?
它可以通过使用来完成globalCompositeOperation
。有多种方法可以自己绘制形状,但这是一种方法(对于演示中的两个矩形圆圈):
更新不知道我怎么会错过明显的,但你当然可以先划圈,然后用复合模式和填充打一个整体——快得多(我想当我想出偏移量时我脑子里已经有了图像重绘)。
屏幕外画布的原因是如果您在主画布上已经有一些背景内容。这将被删除,否则我们打孔的地方。如果什么都没有,则将其绘制到单个画布上没有问题-更新的代码:
/// 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);
我将保留旧代码,因为它可用于无法抚摸的图像 -
现在将填充的形状绘制到离屏画布上。用你想要的轮廓颜色绘制。
/// 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);
要使边框更厚,只需在将形状绘制到主画布时增加偏移量。
这是我目前的解决方案。不需要第二个画布,更容易实现。它仍然使用Ken的想法来使用globalCompositeOperation
:
context.lineWidth = 2;
context.stroke();
var prev = context.globalCompositeOperation;
context.globalCompositeOperation = "destination-out";
context.fill();
context.globalCompositeOperation = prev;