fabric.js
Opened this issue · 0 comments
303182519 commented
https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.2/fabric.min.js
<canvas id="canvas" width="600" height="300"
style="border:1px solid #000000">
</canvas>
fabric.util.object.extend(fabric.Object.prototype, {
// 将圆分成N等份的多边形提高碰撞精度
getCirclePoints: function(number) {
number = number || 8;
const [x, y, r] = [this.left, this.top, this.radius];
const angle = 360 / number;
const points = [];
for(let i = 0; i < number; i++) {
points.push({
x: x + r * Math.cos(angle * i * Math.PI / 180),
y: y + r * Math.sin(angle * i * Math.PI / 180)
})
}
return points;
},
// 获取多边形的相对画布的绝对位置点
getPolygonPoints: function() {
return this.get('points').map(p => {
// @ts-ignore
return fabric.util.transformPoint({
// @ts-ignore
x: ~~ (p.x - this.pathOffset.x),
// @ts-ignore
y: ~~ (p.y - this.pathOffset.y)
}, this.calcTransformMatrix());
});
},
pointToLines: function(points) {
const lines = {}
points.forEach((item, index) => {
lines[`line${index}`] = {
d: item,
o: points[(index + 1) % points.length]
}
});
return lines;
},
// 讲多边形的点换成线,方便对象的包含关系判断
getPolygonToLines: function() {
return this.pointToLines(this.getPolygonPoints());
},
checkCrossPoints: function(point, lines) {
let b1, b2, a1, a2, xi, // yi,
xcount = 0,
iLine;
for (let lineKey in lines) {
iLine = lines[lineKey];
// optimisation 1: line below point. no cross
if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) {
continue;
}
// optimisation 2: line above point. no cross
if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) {
continue;
}
// optimisation 3: vertical line case
if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) {
xi = iLine.o.x;
// yi = point.y;
}
// calculate the intersection point
else {
b1 = 0;
b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);
a1 = point.y - b1 * point.x;
a2 = iLine.o.y - b2 * iLine.o.x;
xi = -(a1 - a2) / (b1 - b2);
// yi = a1 + b1 * xi;
}
// dont count xi < point.x cases
if (xi >= point.x) {
xcount += 1;
}
}
return (xcount !== 0 && xcount % 2 === 1);
},
// 判断一个对象是否再一个对象内,包括任意形状的多边形
checkObjectIsInOtherObject: function(other) {
let type = this.type, lines, points, oType = other.type;
if (type === 'circle') { // 获取圆的点数,默认8个点
points = this.getCirclePoints();
} else if (type === 'polygon') {
points = this.getPolygonPoints();
} else {
points = this.getCoords();
}
if (oType === 'circle') {
lines = other.pointToLines(other.getCirclePoints);
} else if (oType === 'polygon') {
lines = other.getPolygonToLines();
} else {
other.setCoords();
lines = other._getImageLines(other.aCoords);
}
for (let i =0, len = points.length; i < len; i++) {
if (!other.checkCrossPoints(points[i], lines)) {
return false;
}
}
return true;
},
// 检测是否再某个对象里面 intersection 判断是否要相交
isIntersectsWithObject: function(other, intersection) {
let intersectionRes = null;
if (intersection) {
let type = this.type, oType = other.type, points, oPoints;
if (type === 'polygon') {
points = this.getPolygonPoints();
} else if (type === 'circle') {
points = this.getCirclePoints();
} else {
this.setCoords();
points = this.getCoords();
}
if (oType === 'polygon') {
oPoints = other.getPolygonPoints();
} else if (oType === 'circle') {
oPoints = other.getCirclePoints();
} else {
this.setCoords();
oPoints = other.getCoords();
}
intersectionRes = fabric.Intersection.intersectPolygonPolygon(points, oPoints);
console.log(intersectionRes, 'insterction')
}
return intersectionRes && intersectionRes.status === 'Intersection' || this.checkObjectIsInOtherObject(other)
}
})
const canvas = new fabric.Canvas('canvas');
fabric.Object.prototype.transparentCorners = false;
const polygon = new fabric.Polygon([
{x: 140, y: 99},
{x: 160, y: 140},
{x: 216, y: 123},
{x: 200, y: 81},
], {
fill: 'rgba(0, 0, 0, 0.5)'
})
const rect = new fabric.Polygon([
{x: 163, y: 109},
{x: 172, y: 122},
{x: 186, y: 114},
{x: 184, y: 102},
], {
fill: 'rgba(100, 100, 100, 0.5)'
})
canvas.add(rect, polygon).renderAll();
function check () {
canvas.forEachObject(obj => {
if (obj != polygon) {
console.log(obj)
const res = obj.isIntersectsWithObject(polygon, true);
console.log(res);
}
})
}
// polygon.intersectsWithObject(rect)