如何在Javascript中计算二维旋转

如何在Javascript中计算二维旋转,javascript,rotation,trigonometry,Javascript,Rotation,Trigonometry,我对三角不太熟悉,但我只有两个点可以在2D中旋转: *nx, ny . - . - . angle - *cx,cy.................*x,y cx,cy=旋转中心 x、 y=当前x,y nx,ny=新坐标 如何以一定角度计算新点 首先,将旋转中心平移到原点 计算新坐标(nx,ny) 平移回原始旋转中心 步骤1 你的新观点是 中心:

我对三角不太熟悉,但我只有两个点可以在2D中旋转:

                    *nx, ny
               .     -
          .           -
     .  angle          -
*cx,cy.................*x,y
cx,cy=旋转中心
x、 y=当前x,y
nx,ny=新坐标

如何以一定角度计算新点

  • 首先,将旋转中心平移到原点
  • 计算新坐标(nx,ny)
  • 平移回原始旋转中心
  • 步骤1

    你的新观点是

  • 中心:(0,0)
  • 点:(x-cx,y-cy)
  • 步骤2

  • nx=(x-cx)*cos(θ)-(y-cy)*sin(θ)
  • ny=(y-cy)*cos(θ)+(x-cx)*sin(θ)
  • 步骤3

    平移回原始旋转中心:

  • nx=(x-cx)*cos(θ)-(y-cy)*sin(θ)+cx
  • ny=(y-cy)*cos(θ)+(x-cx)*sin(θ)+cy
  • 为了得到更深入的解释,我推荐看一些奇特的图表

    前两个参数是中心点(第二个点将围绕其旋转的原点)的X和Y坐标。接下来的两个参数是我们要旋转的点的坐标。最后一个参数是角度,单位为度

    例如,我们将以点(2,1)为例,围绕点(1,1)顺时针旋转90度

    rotate(1, 1, 2, 1, 90);
    // > [1, 0]
    
    关于此功能的三个注意事项:

  • 对于顺时针旋转,最后一个参数
    角度
    应为正。对于逆时针旋转(如图中所示),它应该是负数

  • 请注意,即使您提供的参数应该产生一个坐标为整数的点,也就是说,将点(5,0)围绕原点(0,0)旋转90度,这应该产生(0,-5)--JavaScript的舍入行为意味着任一坐标仍然可能是一个令人沮丧地接近预期整数的值,但仍然是一个浮点值。例如:

    rotate(0, 0, 5, 0, 90);
    // > [3.061616997868383e-16, -5]
    
    由于这个原因,结果数组的两个元素都应该是浮点。您可以根据需要使用
    Math.round()
    Math.ceil()
    Math.floor()
    将它们转换为整数

  • 最后,请注意,此函数假定为,这意味着Y轴上的值在坐标平面中“向上”时会变高。在HTML/CSS中,Y轴是反向的——当您向下移动页面时,Y轴上的值会变得更高


  • 以上被接受的答案对我来说不正确,旋转是反向的,这里是工作函数

    /*
     CX @ Origin X  
     CY @ Origin Y
     X  @ Point X to be rotated
     Y  @ Point Y to be rotated  
     anticlock_wise @ to rotate point in clockwise direction or anticlockwise , default clockwise 
     return @ {x,y}  
    */
    function rotate(cx, cy, x, y, angle,anticlock_wise = false) {
        if(angle == 0){
            return {x:parseFloat(x), y:parseFloat(y)};
        }if(anticlock_wise){
            var radians = (Math.PI / 180) * angle;
        }else{
            var radians = (Math.PI / -180) * angle;
        }
        var cos = Math.cos(radians);
        var sin = Math.sin(radians);
        var nx = (cos * (x - cx)) + (sin * (y - cy)) + cx;
        var ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
        return {x:nx, y:ny};
     }
    

    我认为最好使用矩阵进行此类操作

    下面是gl矩阵的示例(但您也可以使用类似THREEJS的东西)

    在二维情况下,需要绕z轴旋转:

    rotateVector([x, y, 0], [cX, cY, 0], [0, 0, 1], angleInRadians);
    
    根据:

    • r
      (半径)等于
      旋转中心
      旋转点
    • deg
      (度)是以度为单位测量的角度

    所以你有一个三角形,当给定一个新角度时,你试图计算nx,ny的位置?这应该是“+”。非常感谢。似乎有50%的答案在x公式中有“-”,而另一半答案在y公式中有“-”。在我的例子中,它似乎只在y公式中起作用。这是怎么回事?@Michael我不知道5个月后你是否还在寻找这个问题的答案,但我对函数做了一些编辑,所以现在它更通用了。谢谢!我将不得不重新审视我的工作:我以某种方式解决了问题,它似乎工作正常,但我不记得我现在做了什么…此函数适用于屏幕坐标系,只有旋转方向反转。如果角度为零,则将坐标转换为整数将切掉小数。你至少应该投一个浮点数。此外,您的参数是大写的,您的函数在小写中使用它们。
    import * as glm from 'gl-matrix';
    const rotateVector = (() => {
      
      const q = glm.quat.create();  
      // const m = glm.mat4.create(); // 2nd way
    
      return (v: glm.vec3, point: glm.vec3, axis: glm.vec3, angle: number) => {
    
          glm.quat.setAxisAngle(q, axis, angle);
          // glm.mat4.fromRotation(m, angle, axis); // 2nd way
          glm.vec3.sub(v, v, point);
          glm.vec3.transformQuat(v, v, q);
          // glm.vec3.transformMat4(v, v, m); // 2nd way
          glm.vec3.add(v, v, point);
          return v;
      }
    })();
    
    rotateVector([x, y, 0], [cX, cY, 0], [0, 0, 1], angleInRadians);
    
    x = r * cos(deg)
    y = r * sin(deg)