罗盘 Angle/Rotation 跟踪方向到 X、Y 位置的角度 Javascript

Compass Angle/Rotation Angle For Tracking Direction to X,Y Position In Javascript

假设您有两个 x,y 坐标:起点:(100, 100) 和终点:(96, 105)。所以我需要向左和向上。我想要一个箭头指向目的地的方向,由 css 旋转 属性 旋转,所以我需要角度方向(从 0 到 360)。 0表示直线向上,180表示直线向下,90表示向右,等等

大多数帖子都说通过使用以下方式获得方位角:(Math.atan2(105 - 100, 96 - 100) * 180) / Math.PI;。但我无法让它发挥作用。有了上面的坐标,我得到 128.6598... ,它会在右下方。它还给出负数,这也会把它扔掉。我已经尝试根据它是正数还是负数来添加不同的度数,但没有任何效果。

有没有办法获得这两个点的正确航向(从 0 到 360)?谢谢!

我觉得应该是{end point} - {starting point}

(Math.atan2(96 - 100, 105 - 100) * 180) / Math.PI;
// giving -38.659808254090095 = Down to the right

我认为这不是最好的方法,但应该可行:

const getVectorAngle = ([x1, y1], [x2, y2]) => {
  const x = x2 - x1
  const y = y2 - y1
  return (((Math.acos(y / Math.sqrt(x * x + y * y)) * (Math.sign(x) || 1)) * 180 / Math.PI) + 360) % 360
}

console.log(getVectorAngle([100, 100], [96, 105])) //321.3401

console.log(getVectorAngle([100, 100], [100, 101])) //0
console.log(getVectorAngle([100, 100], [101, 101])) //45
console.log(getVectorAngle([100, 100], [101, 100])) //90
console.log(getVectorAngle([100, 100], [101,  99])) //135
console.log(getVectorAngle([100, 100], [100,  99])) //180
console.log(getVectorAngle([100, 100], [ 99,  99])) //225
console.log(getVectorAngle([100, 100], [ 99, 100])) //270
console.log(getVectorAngle([100, 100], [ 99, 101])) //315
console.log(getVectorAngle([100, 100], [100, 100])) //NaN, start and end values are the same


工作原理如下:

可视化 Geogebra Geometry

r是位移矢量,给定的,我们求α(alpha),那个角度矢量.

const getVectorAngle = ([x1, y1], [x2, y2]) => {
  const x = x2 - x1
  const y = y2 - y1
  return (
      (
        ( //Getting angle by `y = cos(alpha) * r` -> `alpha = cos^-1(y / r)`
          Math.acos(
            y / 
            Math.sqrt(x * x + y * y) //Pythagorean theorem to get the length of r, `r^2 = x^2 + y^2` -> `r = sqrt(x^2 + y^2)`
          ) //= angle in interval [0°; 180°] (in radians)
          * ( //Detect the direction of angle by changing its sign
            Math.sign(x) //Sign of x, +1 if positive, -1 if negative
            || 1         //Return +1 even if x is 0, to avoid cancelling out 180°
          )
        ) //= angle in interval ]-180°; 180°] (still in radians)
        * 180 / Math.PI //Convert angle from radians to degrees
      ) //= angle in degrees
      + 360 //Add 360° to avoid negative values
    ) //= angle in interval ]180°; 540°]
    % 360 //Modulo by 360° to simplify angles >=360°
  //= angle in degrees in interval [0°; 360°[
}

编辑

后来,我意识到,它也可以与 Math.atan2 一起工作:

const getVectorAngle = ([x1, y1], [x2, y2]) => {
  const x = x2 - x1
  const y = y2 - y1
  return x || y
    ? ((Math.atan2(x, y) * 180 / Math.PI) + 360) % 360
    : NaN
}

console.log(getVectorAngle([100, 100], [96, 105])) //321.3401

console.log(getVectorAngle([100, 100], [100, 101])) //0
console.log(getVectorAngle([100, 100], [101, 101])) //45
console.log(getVectorAngle([100, 100], [101, 100])) //90
console.log(getVectorAngle([100, 100], [101,  99])) //135
console.log(getVectorAngle([100, 100], [100,  99])) //180
console.log(getVectorAngle([100, 100], [ 99,  99])) //225
console.log(getVectorAngle([100, 100], [ 99, 100])) //270
console.log(getVectorAngle([100, 100], [ 99, 101])) //315
console.log(getVectorAngle([100, 100], [100, 100])) //NaN, start and end values are the same

您可能会注意到,计算的外部 shell 保持不变。那是因为 Math.atan2 已经 return 在区间 ]-180°;180°] 中以弧度为单位的角度;所以它在功能上与第一个解决方案的内部部分相同。

唯一的变化是对空向量进行额外检查:Math.atan2 在这种情况下不会 return NaN