我正在设计白板,我想在两个节点之间画线,如何检查两个节点之间的距离是否在视口两侧垂直或水平 如图所示,我想检测它是否在里面 就像节点 1 和节点 2 之间的线在内部,节点 1 和节点 3 之间的线 inside 是 Outside,节点 2 和节点 4 之间的线是 inside
我尝试了很多解决方案
一点数学:
经过两点 (x1,y1) 和 (x2,y2) 的线是
y=y1+(x-x1)*(y2-y1)/(x2-x1)
看到当x=x1时,y变成y1,如果x=x2,y变成y2。我们可以使用
const m=(y2-y1)/(x2-x1)
const x0=y1-m*x1
y=x0+m*x //<--this is the new line equation
如果我们想象一个左下角位于 (0,0) 位置的矩形,我们需要知道宽度和高度的尺寸
when x=0 if y>0 and y<height
when x=width if y>0 and y<height
when y=0 if x>0 and x<width
when y=height if x>0 and x<width
此外,我们还需要考虑这两个点都在线两侧或者两个点都在矩形内部。为此,我们乘以坐标
when x=0 x1*x2<0 or inside both
when x=width (x1-width)*(x2-width)<0 or inside both
when y=0 y1*y2<0 or inside both
when y=height (y1-heigth)*(y2-heigth)<0 or inside both
一般来说,在使微积分“平移”点坐标之前,“矩形”并不位于我们需要的位置 (0,0)。我们将 HTMLElements 的 getBoundingClientRect() 传递给我们的函数,因此我们会妨碍它
checkPosition(point1:{left:number,top:number},
point2:{left:number,top:number},
rect:{left:number,top:number,width:number,height:number})
并调用函数为
this.checkPosition(point1.getBoundingClientRect(),
point2.getBoundingClientRect(),
rectangle.getBoundingClientRect())
好吧,我们的函数就像
checkPosition(point1:{left:number,top:number},
point2:{left:number,top:number},
rect:{left:number,top:number,width:number,height:number})
{
//"translate" the points
const x1=point1.left-rect.left
const y1=point1.top-rect.top
const x2=point2.left-rect.left
const y2=point2.top-rect.top
const a=rect.width;
const b=rect.height;
//intermediate calculus
const m=(y2-y1)/(x2-x1)
const x0=y1-m*x1
//we return an object in the way:
//{bottom:boolean,top:boolean,left:boolean,right:boolean}
const insideboth=(x1>0 && x1<a && y1>0 && y1<b) && (x2>0 && x2<a && y2>0 && y2<b)
return {top:-x0/m>0 && -x0/m<a && (y1*y2<0 || insideboth), // cut the base of the rectangle
bottom:(b-x0)/m>0 && (b-x0)/m<a && ((y1-b)*(y2-b)<0 || insideboth), //cut the top of the rectangle
left:x0>0 && x0<b && (x1*x2<0 || insideboth), //cut the left border
right:x0+m*a>0 && x0+m*a<b && ((x1-a)*(x2-a)<0 || insideboth) //cut the right border
}
}
我做了一个小stackblitz,你可以“玩”拖动点或矩形,看看当相交完成时矩形的边框如何变成红色。
注意:如果我们只需要计算是否有边界,我们不需要计算所有边界,所以我们不需要返回一个对象
checkPosition(point1:{left:number,top:number},
point2:{left:number,top:number},
rect:{left:number,top:number,width:number,height:number})
{
const x1=point1.left-rect.left
const y1=(point1.top-rect.top)
const x2=point2.left-rect.left
const y2=(point2.top-rect.top)
const a=rect.width;
const b=rect.height;
const insideboth=(x1>0 && x1<a && y1>0 && y1<b) && (x2>0 && x2<a && y2>0 && y2<b)
if (insideboth) //<--no more check
return true;
const m=(y2-y1)/(x2-x1)
const x0=y1-m*x1
if (-x0/m>0 && -x0/m<a && y1*y2<0) //<--no more check
return true
if (-x0/m>0 && -x0/m<a && y1*y2<0)
return true
if ((b-x0)/m>0 && (b-x0)/m<a && (y1-b)*(y2-b)<0)
return true
if (x0>0 && x0<b && x1*x2<0)
return true
if (x0+m*a>0 && x0+m*a<b && (x1-a)*(x2-a)<0)
return true
}