如何使用HMTL5 Javascript Canvas获得碰撞的三个形状的交集并删除未碰撞的部分?

Pro*_*ter 4 html javascript canvas html5-canvas konvajs

我最近在这里专门针对 KonvaJs 发布了一个类似的问题,但是,我没有得到任何答案,并想直接进入 KonvaJs 使用的根源。我想知道是否有使用 HMTL5 Javascript Canvas 解决以下问题的标准方法。

如果给我 3 个圆圈并将它们定位为原色圆圈(3 个圆圈彼此相交),是否有一个功能可以帮助我删除不与任何东西碰撞的部分并只保留相交的部分?

另一个示例可能是以形成三角形的方式绘制三条线。通过删除没有碰撞的部分,我们最终会得到 3 个点(至少在视觉上,不确定我最终是总共得到 3 个还是堆叠起来得到 6 个),它们是前一个三角形的边缘。

根据我搜索的内容,我可以通过使用命中区域来检测碰撞区域,然后以某种方式在碰撞的部分上应用剪辑功能,以仅获得所需的结果。我在这个解决方案中看到的问题是,如果每个形状都是可拖动的,则形状可能会被剪裁,但不会跟随拖动的形状。

我的另一个想法是检测并切割碰撞区域,然后删除没有碰撞的区域,然后将它们组合在一起。(我不知道怎么把它们切成小块……)

我不确定上面提到的任何想法是否是解决它的正确/最佳方法......

Kai*_*ido 5

合成可以做到这一点。

诀窍是在第二个屏幕外画布上处理每个合成,然后使用默认source-over模式合并它们。

const canvas = document.getElementById( "canvas" );
const ctx = canvas.getContext( "2d" );
// we create an off-screen copy of the canvas to perform our clippings
const copy = canvas.cloneNode();
const off = copy.getContext( "2d" );

// declares our shapes
const circle = new Path2D();
circle.arc( 0, 0, 145, 0, Math.PI * 2 );
const blue_circle = new Path2D();
blue_circle.addPath( circle, { e: 260, f: 160 } );
const red_circle = new Path2D();
red_circle.addPath( circle, { e: 160, f: 310 } );
const yellow_circle = new Path2D();
yellow_circle.addPath( circle, { e: 340, f: 310 } );

// get common area of blue & red
off.fill( blue_circle );
off.globalCompositeOperation = "source-in";
off.fill( red_circle );
// save to visible canvas
ctx.drawImage( copy, 0, 0 )

// clear
off.globalCompositeOperation = "source-over";
off.clearRect( 0, 0, 500, 500 );
// get common area of blue & yellow
off.fill( blue_circle );
off.globalCompositeOperation = "source-in";
off.fill( yellow_circle );
// save to visible canvas
ctx.drawImage( copy, 0, 0 )

// clear
off.globalCompositeOperation = "source-over";
off.clearRect( 0, 0, 500, 500 );
// get common area of red & yellow
off.fill( red_circle );
off.globalCompositeOperation = "source-in";
off.fill( yellow_circle );
// save to visible canvas
ctx.drawImage( copy, 0, 0 );

// last pass to blend the colors
off.globalCompositeOperation = "source-over";
off.clearRect( 0, 0, 500, 500 );
off.globalAlpha = 0.6;
off.fillStyle = "blue";
off.fill( blue_circle );
off.fillStyle = "red";
off.fill( red_circle );
off.fillStyle = "yellow";
off.fill( yellow_circle );

// draw only where we did draw previously
ctx.globalCompositeOperation = "source-in";
ctx.drawImage( copy, 0, 0 );
Run Code Online (Sandbox Code Playgroud)
canvas { background: white }
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" width="500" height="500"></canvas>
Run Code Online (Sandbox Code Playgroud)

改用线条:

const canvas = document.getElementById( "canvas" );
const ctx = canvas.getContext( "2d" );
// we create an off-screen copy of the canvas to perform our clippings
const copy = canvas.cloneNode();
const off = copy.getContext( "2d" );
off.lineWidth = 30;

const bottom_left_top_center = new Path2D("M0,300L300,0");
const top_left_bottom_right = new Path2D("M0,0L300,300");
const bottom_left_bottom_right = new Path2D("M0,200L300,200");

off.stroke( bottom_left_top_center );
off.globalCompositeOperation = "source-in";
off.stroke( top_left_bottom_right );

// save to visible canvas
ctx.drawImage( copy, 0, 0 )

// clear
off.globalCompositeOperation = "source-over";
off.clearRect( 0, 0, 500, 500 );

off.stroke( bottom_left_top_center );
off.globalCompositeOperation = "source-in";
off.stroke( bottom_left_bottom_right );
// save to visible canvas
ctx.drawImage( copy, 0, 0 )

// clear
off.globalCompositeOperation = "source-over";
off.clearRect( 0, 0, 500, 500 );

off.stroke( top_left_bottom_right );
off.globalCompositeOperation = "source-in";
off.stroke( bottom_left_bottom_right );
// save to visible canvas
ctx.drawImage( copy, 0, 0 )
Run Code Online (Sandbox Code Playgroud)
canvas { background: white }
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" width="300" height="300"></canvas>
Run Code Online (Sandbox Code Playgroud)