填充内部多边形的外部区域

时间:2015-12-06 23:22:17

标签: javascript html5-canvas

我正在shipVertexes数组中绘制一个有4个点的船。 在船内,我用stunVertexes绘制了相同的形状。

抚摸上下文会产生附加图像。你可以看到较大的船内有一艘小船。 (红船)

我想填补外船和外滩之间的空间。内船,在中间留下一个空的(黑色)空间。

当我运行context.fill()时,整个空间都是实心的(参见黄色船只)。

如何填写室内空间?

enter image description here

3 个答案:

答案 0 :(得分:2)

除了使用2填充操作和全局合成之外,还有一种更快的方法。

另请注意,使用合成进行擦除将擦除监视器位于船的孔中。如果背景中有一些装饰会丢失。在这种情况下,它看起来是正确的,因为你有一个显示正文标记颜色的空背景。

填充操作有两种方法可以了解形状内部和外部的内容。最常用的是非零规则:

'非零'缠绕

这种缠绕规则是最常用的,也是Canvas 2D支持的唯一规则。

要确定某个点是否落在曲线内,您可以在该点绘制一条虚线。接下来,您将计算该线在到达该点之前穿过曲线的次数。对于每个顺时针旋转,您减去1,对于每个逆时针旋转,您加1。

non zero rule

要将非零windind应用到您的船上,我将内部船舶的绘制顺序更改为逆时针,并自动生成孔。

如果更改订单太复杂,您可以检查您的浏览器是否支持奇怪的规则:

'偶数'缠绕

要确定一个点是否落在路径内,您再次在该点上绘制一条线。这一次,您只需添加穿越路径的次数。如果总数是偶数,则该点在外;如果它很奇怪,重点在于内部。路径的绕组被忽略。例如:

enter image description here

对于这条规则我只是复制了您的原始代码,填写后我指定了' evenodd';



var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

ctx.fillStyle='red';
//ship copy 1
ctx.beginPath();
ctx.moveTo(50,0);
ctx.lineTo(100,25);
ctx.lineTo(50,150);
ctx.lineTo(0,25);
ctx.moveTo(50,10);
ctx.lineTo(20,25);
ctx.lineTo(50,100);
ctx.lineTo(80,25);
ctx.closePath();
ctx.fill();

//ship copy 2
ctx.beginPath();
ctx.translate(180, 0);
ctx.moveTo(50,0);
ctx.lineTo(100,25);
ctx.lineTo(50,150);
ctx.lineTo(0,25);
ctx.moveTo(50,10);
ctx.lineTo(80,25);
ctx.lineTo(50,100);
ctx.lineTo(20,25);
ctx.closePath();
ctx.fill('evenodd');

body{ background-color: black; }
#canvas{border:1px solid red;}

<canvas id="canvas" width=300 height=300></canvas>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

最简单的是用红色填充所有船只,然后用黑色填充内部船只:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.moveTo(50, 0);
ctx.lineTo(100, 25);
ctx.lineTo(50, 150);
ctx.lineTo(0, 25);
ctx.fillStyle = 'red';
ctx.fill();

ctx.beginPath();
ctx.moveTo(50, 10);
ctx.lineTo(20, 25);
ctx.lineTo(50, 100);
ctx.lineTo(80, 25);
ctx.closePath();
ctx.fillStyle = 'black';
ctx.fill();
body {
  background-color: black;
}
#canvas {
  border: 1px solid red;
}
<canvas id="canvas" width=300 height=300></canvas>

答案 2 :(得分:0)

使用合成从较大的形状中“擦除”较小的形状。

enter image description here

特别是,destination-out合成将使用新图纸“擦除”。

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

ctx.fillStyle='red';

ctx.beginPath();
ctx.moveTo(50,0);
ctx.lineTo(100,25);
ctx.lineTo(50,150);
ctx.lineTo(0,25);
ctx.closePath();
ctx.fill();

ctx.beginPath();
ctx.moveTo(50,10);
ctx.lineTo(80,25);
ctx.lineTo(50,100);
ctx.lineTo(20,25);
ctx.closePath();
// use compositing to "erase" the smaller shape from the bigger shape
ctx.globalCompositeOperation='destination-out';
ctx.fill();
ctx.globalCompositeOperation='source-over';
body{ background-color: black; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>