我正在shipVertexes
数组中绘制一个有4个点的船。
在船内,我用stunVertexes
绘制了相同的形状。
抚摸上下文会产生附加图像。你可以看到较大的船内有一艘小船。 (红船)
我想填补外船和外滩之间的空间。内船,在中间留下一个空的(黑色)空间。
当我运行context.fill()
时,整个空间都是实心的(参见黄色船只)。
如何填写室内空间?
答案 0 :(得分:2)
除了使用2填充操作和全局合成之外,还有一种更快的方法。
另请注意,使用合成进行擦除将擦除监视器位于船的孔中。如果背景中有一些装饰会丢失。在这种情况下,它看起来是正确的,因为你有一个显示正文标记颜色的空背景。
填充操作有两种方法可以了解形状内部和外部的内容。最常用的是非零规则:
'非零'缠绕
这种缠绕规则是最常用的,也是Canvas 2D支持的唯一规则。
要确定某个点是否落在曲线内,您可以在该点绘制一条虚线。接下来,您将计算该线在到达该点之前穿过曲线的次数。对于每个顺时针旋转,您减去1,对于每个逆时针旋转,您加1。
要将非零windind应用到您的船上,我将内部船舶的绘制顺序更改为逆时针,并自动生成孔。
如果更改订单太复杂,您可以检查您的浏览器是否支持奇怪的规则:
'偶数'缠绕
要确定一个点是否落在路径内,您再次在该点上绘制一条线。这一次,您只需添加穿越路径的次数。如果总数是偶数,则该点在外;如果它很奇怪,重点在于内部。路径的绕组被忽略。例如:
对于这条规则我只是复制了您的原始代码,填写后我指定了' 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;
答案 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)
使用合成从较大的形状中“擦除”较小的形状。
特别是,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>