如何知道线是否在视口内

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

我正在设计白板,我想在两个节点之间画线,如何检查两个节点之间的距离是否在视口两侧垂直或水平 如图所示,我想检测它是否在里面 就像节点 1 和节点 2 之间的线在内部,节点 1 和节点 3 之间的线 insideOutside,节点 2 和节点 4 之间的线是 inside

enter image description here

我尝试了很多解决方案

angular line between whiteboard
1个回答
0
投票

一点数学:

经过两点 (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
  }
© www.soinside.com 2019 - 2024. All rights reserved.