如果我创建两个相邻的矩形并测试它们的交集,它总是返回true,即使它不应该。
从小提琴中可以看出,如果从x=0
和width=50px
开始,第二个矩形需要从x=50
开始,以避免介于两者之间。但是,为避免交叉,必须有2px的间隙。
为什么会这样,我该如何解决这个问题?
canvas = new fabric.Canvas('canvas');
// Starting at x=0
var rect1 = new fabric.Rect({
left: 0, top: 0, fill: 'black', width: 50, height: 50, selectable: false,
});
// Starting 50px right of the previous
var rect2 = new fabric.Rect({
left: 50, top: 0, fill: 'blue', width: 50, height: 50, selectable: false,
});
// Starting 51px right of the previous
var rect3 = new fabric.Rect({
left: 101, top: 0, fill: 'black', width: 50, height: 50, selectable: false,
});
// Starting 52px right of the previous
var rect4 = new fabric.Rect({
left: 153, top: 0, fill: 'blue', width: 50, height: 50, selectable: false,
});
canvas.add(rect1, rect2, rect3, rect4);
console.log(rect1.aCoords.tr, rect2.aCoords.tr, rect3.aCoords.tr, rect4.aCoords.tr);
if (rect1.intersectsWithObject(rect2))
console.log("1st intersecting with 2nd.");
else
console.log("No intersection between 1st and 2nd.");
if (rect2.intersectsWithObject(rect3))
console.log("2nd intersecting with 3rd.");
else
console.log("No intersection between 2nd and 3rd.");
if (rect3.intersectsWithObject(rect4))
console.log("3rd intersecting with 4th.");
else
console.log("No intersection between 3rd and 4th.");

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.js"></script>
<p>Open console to see the rectangles absolute positions.</p>
<canvas id="canvas" width="300px" height="75px"></canvas>
&#13;
我的jsfiddle
答案 0 :(得分:1)
我认为这是因为不可见的笔画宽度(默认为1)而发生的。
因此在矩形中,它们需要2px的间隙(左边为1px,右边为1px)。 我在你的样本上设置了笔划宽度为0px并再次运行测试。
canvas = new fabric.Canvas('canvas');
// Starting at x=0
var rect1 = new fabric.Rect({
left: 0, top: 0, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
});
// Starting 50px right of the previous
var rect2 = new fabric.Rect({
left: 51, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
});
// Starting 51px right of the previous
var rect3 = new fabric.Rect({
left: 102, top: 0, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
});
// Starting 52px right of the previous
var rect4 = new fabric.Rect({
left: 153, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
});
//canvas.add(rect1, rect2, rect3, rect4);
canvas.add(rect1);
canvas.add(rect2);
canvas.add(rect3);
canvas.add(rect4);
console.log(rect1.aCoords.tr, rect2.aCoords.tr, rect3.aCoords.tr, rect4.aCoords.tr);
if (rect1.intersectsWithObject(rect2))
console.log("1st intersecting with 2nd.");
else
console.log("No intersection between 1st and 2nd.");
if (rect2.intersectsWithObject(rect3))
console.log("2nd intersecting with 3rd.");
else
console.log("No intersection between 2nd and 3rd.");
if (rect3.intersectsWithObject(rect4))
console.log("3rd intersecting with 4th.");
else
console.log("No intersection between 3rd and 4th.");
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js"></script>
<p>Open console to see the rectangles absolute positions.</p>
<canvas id="canvas" width="300px" height="75px"></canvas>
选中fiddle。
答案 1 :(得分:1)
我通过使用Fabric.js的低级函数解决了这个问题。如果找到了一个交叉点,我会检查是否只有一个交叉点,以及该点是否是我们其中一个对象的一个角。如果是真的,我们有一个假的交叉点&#34;。
function isIntersecting(obj1, obj2) {
var result = new fabric.Intersection(),
points1 = obj1.getCoords(true, false),
points2 = obj2.getCoords(true, false),
length1 = points1.length,
length2 = points2.length,
a1, a2, b1, b2;
// Check if one object lies within the other.
if (obj1.isContainedWithinObject(obj2, false, true) || obj2.isContainedWithinObject(obj1, false, true))
return true;
// Check for intersection between all edges.
for (var i = 0; i < length1; i++) {
a1 = points1[i];
a2 = points1[(i + 1) % length1];
for (var j = 0; j < length2; j++) {
b1 = points2[j];
b2 = points2[(j + 1) % length2];
result = fabric.Intersection.intersectLineLine(a1, a2, b1, b2);
if (result.status == 'Intersection') {
// It's not an intersection if we have only 1 intersection point and if this one is the end of one of our lines.
let allPoints = [a1, a2, b1, b2];
if (result.points.length > 1 || !polygonIncludesPoint(allPoints, result.points[0])) {
return true;
}
else if (obj2.containsPoint(a1) || obj2.containsPoint(a2) ||
obj1.containsPoint(b1) || obj1.containsPoint(b2)) {
// But it is if one corner of an edge is within the other object.
return true;
}
}
}
}
return false;
}
function polygonIncludesPoint(points, point) {
for (var i = 0; i < points.length; i++) {
if (points[i].eq(point))
return true;
}
return false;
}
var canvas = new fabric.Canvas('canvas');
var center = new fabric.Rect({
left: 50, top: 50, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var tl = new fabric.Rect({
left: 0, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var tm = new fabric.Rect({
left: 50, top: 0, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var tr = new fabric.Rect({
left: 100, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var ml = new fabric.Rect({
left: 0, top: 50, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var mr = new fabric.Rect({
left: 100, top: 50, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var bl = new fabric.Rect({
left: 0, top: 100, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var bm = new fabric.Rect({
left: 50, top: 100, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var br = new fabric.Rect({
left: 80, top: 80, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var center2 = new fabric.Rect({
left: 180, top: 20, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var bigRect = new fabric.Rect({
left: 180, top: 20, fill: 'rgba(0, 0, 255, 0.3)', width: 90, height: 90, selectable: false, strokeWidth: 0
});
var center3 = new fabric.Rect({
left: 310, top: 40, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
});
var bigRect2 = new fabric.Rect({
left: 290, top: 20, fill: 'rgba(0, 0, 255, 0.3)', width: 90, height: 90, selectable: false, strokeWidth: 0
});
canvas.add(center, tl, tm, tr, ml, mr, bl, bm, br, center2, bigRect, center3, bigRect2);
var objects = canvas.getObjects('rect');
// Check 1st case
console.log("1st case:");
objects.forEach(function (targ) {
if (targ === center || targ === center2 || targ === bigRect || targ === center3 || targ === bigRect2) return;
if (isIntersecting(center, targ))
console.log("Intersection");
else
console.log("No intersection");
});
// Check 2nd case
console.log("2nd case:");
if (isIntersecting(center2, bigRect))
console.log("Intersection");
else
console.log("No intersection");
// Check 3rd case
console.log("3rd case");
if (isIntersecting(center3, bigRect2))
console.log("Intersection");
else
console.log("No intersection");
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js"></script>
<p>See console for results.</p>
<canvas id="canvas" width="400px" height="200px"></canvas>
&#13;
我的jsfiddle
答案 2 :(得分:1)
要添加更多细节,您应该考虑路径而不是像素。
宽50且从0开始的矩形实际上与另一个从50开始的矩形交叉,考虑它们的边完全重叠,两个镜之间没有空间,它们相互接触。
我同意可以添加一个参数,以便在返回布尔值时不考虑重叠。