两个path2D之间的javascript画布交集

问题描述 投票:0回答:1

我正在寻找一种方法来检查两个 path2D 是否相交,但找不到方法...

示例:

// My circle
let circlePath = new Path2D();
circlePath.ellipse(x, y, radiusX, radiusY, 0, 0, Math.PI*2, false);

// My rectangle
let rectPath = new Path2D();
rectPath.rect(x, y, width, height);

// Intersect boolean
let intersect = circlePath.intersect(rectPath); // Does not exists

有没有一个函数可以做到这一点?

我发现

isPointInPath(path2D, x, y)
(我用我的路径来检查与鼠标的相交),但不能在两条路径之间使用它。

或者也许是一种获取 Path2D 中所有点的数组以将

isPointInPath
与所有点一起使用的方法?

编辑:

仅供参考,我希望将其用于游戏开发,我希望能够检查实体之间的碰撞(实体由一些数据和 Path2D 定义)。我的实体可以是正方形、圆形或更复杂的形状。

javascript canvas html5-canvas
1个回答
3
投票

目前 API 中没有任何内容可以执行此操作。

Path2D 接口仍然只是一个不透明的对象,我们甚至无法从中提取路径数据。实际上,我确实开始制定未来的提案,公开此路径数据并向 Path2D 对象添加更多方法,例如

getPointAtLength()
,或导出到 SVG 路径命令,这将有助于做你想做的事情,但我在它成为 API 的一部分之前我不会屏住呼吸,而且我必须承认我什至没有考虑过包含这样的路径相交方法...

但是,作为这项工作的一部分,我确实构建了该 API 的原型,目前仅公开了一些预期的方法:https://github.com/Kaiido/path2D-inspection/
在这些方法中,有一个

toSVGString()
可以与这个项目一起使用(我没有广泛测试)。

因此我们可以通过合并两个库来构建

Path2D#intersects()
。但请注意,至少我的(path2d-inspection)尚未经过广泛测试,我不建议在生产中使用它。
不管怎样,这里有一个非常快速的黑客作为概念验证:

.as-console-wrapper { max-height: 50px !important }
<script src="https://cdn.jsdelivr.net/gh/Kaiido/path2D-inspection@master/build/path2D-inspection.min.js"></script>
<script type=module>
import intersect from "https://cdn.jsdelivr.net/gh/bpmn-io/path-intersection@master/intersect.js";
// Move the intersect script as Path2D methods:
{
  Path2D.prototype.getIntersections = function(path2) {
    return intersect(this.toSVGString(), path2.toSVGString());
  };
  Path2D.prototype.intersects = function(path2) {
    return this.getIntersections(path2).length > 0;
  };
}

const circlePath = new Path2D();
circlePath.ellipse(rand(100, 20), rand(100, 20), rand(80, 10), rand(80, 10), rand(Math.PI*2), 0, Math.PI*2, false);

// My rectangle
const rectPath = new Path2D();
rectPath.rect(rand(150), rand(100), rand(200), rand(200));

// Intersect boolean
const intersection = rectPath.intersects(circlePath);
console.log("intersect:", intersection);

// List of intersection points
const intersections = rectPath.getIntersections(circlePath);
console.log(intersections);

// Render on a canvas to verify
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.strokeStyle = "green";
ctx.stroke(circlePath);
ctx.strokeStyle = "red";
ctx.stroke(rectPath);

function rand(max=1, min=0) {
  return Math.random() * (max - min) + min;
}
</script>
<canvas></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.