JS如何使用Math.atan2獲取兩點之間角度的實踐案例


本文主要介紹使用如何實現手動拖拽旋轉元素的效果。

1、簡述

最近在研究如何實現手動控制元素的旋轉效果,在網上找了很多,都沒有找出類似的實現,因此經過一些調研和計算,最終完美實現效果,在這里記錄下來。

2、效果展示

通過手動旋轉的方式,實現組件的360度無縫旋轉。圖示是實現結果的幾個截圖:

  • 0deg

  • 順時針轉到 66deg

  • 逆時針轉到 315deg

  • 轉到 180deg

3、實現分析

如圖所示,實現難點在於計算出兩點間連線的傾斜角 angle

這里需要掌握的幾個知識點:

3.1 獲取轉動的角度

使用 Math.atan2() 函數可以非常高效的實現之,它是返回點與原點之間的傾斜角,如圖所示,如果想計算出點 (x1,y1) 與 原點 (cx,cy) 與X軸的角度,只需要執行:

Math.atan2(y1 - cy, x1 - cx)

需要注意的是,它的取值范圍是[-PI, PI]。
當 (x1, y1) 在第一象限, 0 < θ < PI/2

當 (x1, y1) 在第二象限 PI/2 < θ≤PI

當 (x1, y1) 在第三象限, -PI < θ < -PI/2

當 (x1, y1) 在第四象限, -PI/2 < θ < 0

3.2 角度與弧度之間的轉換

角度 = 弧度 * 180 / Math.PI;
弧度= 角度 * Math.PI / 180;

3.3 組件中心點位置計算

使用getBoundingClientRect() 的方法可以獲取出容器的位置信息,用當前位置減去寬/高的一半,即可獲取中心點位置。

  //中心點
  cx = x + width / 2;
  cy = y + height / 2;

4、最終代碼

/**
 * 獲得旋轉夾角
 * @param {*} x1 旋轉點1
 * @param {*} y1 
 * @param {*} x2 旋轉點2
 * @param {*} y2 
 */
function getAngle(x1, y1, x2, y2) {
  // 獲取組件的位置信息
  let rect = document.getElementsByClassName('active-ele')[0].getBoundingClientRect();
  let {
    x,
    y,
    width,
    height
  } = rect;

  //中心點
  let cx = x + width / 2;
  let cy = y + height / 2;

  //2個點之間的角度獲取
  let c1 = Math.atan2(y1 - cy, x1 - cx) * 180 / (Math.PI);
  let c2 = Math.atan2(y2 - cy, x2 - cx) * 180 / (Math.PI);
  let angle;
  c1 = c1 <= -90 ? (360 + c1) : c1;
  c2 = c2 <= -90 ? (360 + c2) : c2;

  //夾角獲取
  angle = Math.floor(c2 - c1);
  angle = angle < 0 ? angle + 360 : angle;
  return angle;
}
    /**
     * 獲得旋轉夾角
     * @param startPos.x 指的是初始位置的x坐標
     * @param startPos.y 指的是初始位置的y坐標
     * @param startPos.r 指的是初始的旋轉角度
     */
    let angle = getAngle(startPos.x, startPos.y, e.x, e.y);
    let startAngle = startPos.r;
    let deg;

    // 賦值的旋轉角度
    let rotate;

    // 順時針旋轉
    if (e.x - startX > 0) {
      deg = startAngle + angle;
      rotate = deg > 360 ? deg - 360 : deg;
    } else {
    // 逆時針旋轉
      angle = 360 - angle;
      deg = startAngle - angle;
      rotate = deg < 0 ? deg + 360 : deg;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM