如何使用HMTL5 Javascript Canvas使三个形状的交集发生碰撞并删除不发生碰撞的零件? [英] How can I get the intersection of three shapes colliding and delete the parts that are not colliding using HMTL5 Javascript Canvas?

查看:49
本文介绍了如何使用HMTL5 Javascript Canvas使三个形状的交集发生碰撞并删除不发生碰撞的零件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近针对KonvaJs发表了一个类似的问题

I've recently posted a similar question specifically for KonvaJs here, however, I have not gotten any answer and wanted to go directly to the root of what KonvaJs uses. I would like to know if there's a standard way of solving the following problem using HMTL5 Javascript Canvas.

如果给我3个圆并将它们定位为原色圆(3个相交的圆),是否有一个功能可以帮助我删除没有碰撞的部分并仅保留相交的部分?

If I am given 3 circles and they are positioned as the primary color circles (3 circles intersecting each other), is there a function that might help me to delete the parts that are not colliding with anything and just keep the intersecting parts?

另一个示例可能是绘制三条线,使其形成一个三角形.通过删除不发生碰撞的部分,我们将得到3个点(至少从视觉上来说,不确定我最终得到的总点数是3点还是6点),这就是上一个三角形的边缘.

Another example could be drawing three lines in such a way that it forms a triangle. By deleting the parts that are not colliding, we would end up with 3 points (at least visually, not sure if I end up with 3 in total or 6 from stacking up), which are the edges of the previous triangle.

根据搜索到的内容,我可以使用剪辑功能在发生碰撞的零件上只能获得所需的结果.我看到的这种解决方案的问题是,如果每个形状都是可拖动的,则这些形状可能会被裁剪,但不会跟随所拖动的形状.

Based on what I've searched, I could detect the collided area by using the hit region and then somehow applying the clip function over the parts that are colliding to only get the desired result. The problem I see with this solution is that if every shape is draggable, the shapes might be clipped but not follow the dragged shape.

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

Another idea I've had is to detect and cut the collided areas and then delete the areas with no collision and then group them together. (I do not know how to cut them into small pieces...)

我不确定上述任何想法是否是解决该问题的正确/最佳方法...

I'm not sure if any of the mentioned ideas are the correct/best way to solve it...

推荐答案

技巧是处理第二个屏幕外画布上的每个合成,然后使用默认的 source-over 模式将它们合并.

The trick is to process each compositing on a second off-screen canvas, and then merge them using the default source-over mode.

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 );

canvas { background: white }

<canvas id="canvas" width="500" height="500"></canvas>

改为使用行:

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 )

canvas { background: white }

<canvas id="canvas" width="300" height="300"></canvas>

这篇关于如何使用HMTL5 Javascript Canvas使三个形状的交集发生碰撞并删除不发生碰撞的零件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆