填充内部多边形的外部区域
Fill in outer area of an interior polygon
我正在用 shipVertexes
数组中的 4 个点绘制一艘船。
在船内,我正在用 stunVertexes
.
绘制较小的相同形状
抚摸上下文会产生附加图像。你可以看到大船里面有一艘小船。 (红船)
我要填外船和内船之间的space,中间留空(黑色)space
当我运行context.fill()
时,整个space都是实心的(见黄船)。
如何只填写内部的外部 space?
使用合成 "erase" 从较大的形状到较小的形状。
特别是,destination-out
合成将 "erase" 使用新绘图。
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>
除了使用 2 次填充操作和全局合成之外,还有一种更快的方法。
另请注意,使用合成进行擦除会擦除船洞中的所有内容。如果背景中有一些装饰会丢失。在这种情况下它看起来是正确的,因为你有一个显示正文标签颜色的空白背景。
填充操作有两种理解形状内部和外部的方式。最常用的是非零规则:
‘非零’绕组
这个缠绕规则是最常用的,也是Canvas 2D唯一支持的规则。
要确定一个点是否落在曲线内,您可以通过该点画一条假想线。接下来,您将计算该线在到达该点之前与曲线相交的次数。每顺时针旋转减 1,每逆时针旋转加 1。
为了将非零风力应用到你的船上,我将内部船的绘图顺序更改为逆时针方向,它会自动产生孔。
如果更改顺序过于复杂,您可以检查您的浏览器是否支持奇偶规则:
‘奇偶’绕组
要确定一个点是否落在路径内,您再次通过该点画一条线。这一次,您只需添加穿过路径的次数。如果总数是偶数,则点在外面;如果是奇数,则点在里面。路径的弯曲被忽略。例如:
对于此规则,我只是复制了您的原始代码,并在填写时指定了 '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>
最简单的就是把所有的船都填成红色,然后把里面的船填成黑色:
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>
我正在用 shipVertexes
数组中的 4 个点绘制一艘船。
在船内,我正在用 stunVertexes
.
抚摸上下文会产生附加图像。你可以看到大船里面有一艘小船。 (红船)
我要填外船和内船之间的space,中间留空(黑色)space
当我运行context.fill()
时,整个space都是实心的(见黄船)。
如何只填写内部的外部 space?
使用合成 "erase" 从较大的形状到较小的形状。
特别是,destination-out
合成将 "erase" 使用新绘图。
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>
除了使用 2 次填充操作和全局合成之外,还有一种更快的方法。
另请注意,使用合成进行擦除会擦除船洞中的所有内容。如果背景中有一些装饰会丢失。在这种情况下它看起来是正确的,因为你有一个显示正文标签颜色的空白背景。
填充操作有两种理解形状内部和外部的方式。最常用的是非零规则:
‘非零’绕组
这个缠绕规则是最常用的,也是Canvas 2D唯一支持的规则。
要确定一个点是否落在曲线内,您可以通过该点画一条假想线。接下来,您将计算该线在到达该点之前与曲线相交的次数。每顺时针旋转减 1,每逆时针旋转加 1。
为了将非零风力应用到你的船上,我将内部船的绘图顺序更改为逆时针方向,它会自动产生孔。
如果更改顺序过于复杂,您可以检查您的浏览器是否支持奇偶规则:
‘奇偶’绕组
要确定一个点是否落在路径内,您再次通过该点画一条线。这一次,您只需添加穿过路径的次数。如果总数是偶数,则点在外面;如果是奇数,则点在里面。路径的弯曲被忽略。例如:
对于此规则,我只是复制了您的原始代码,并在填写时指定了 '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>
最简单的就是把所有的船都填成红色,然后把里面的船填成黑色:
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>