zoukankan      html  css  js  c++  java
  • 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;
        }
    
  • 相关阅读:
    GlassFish 3.1 正式版发布
    NetBeans 时事通讯(刊号 # 137 Mar 03, 2011)
    在Win7上安装AutoCAD2007碰到的问题及其解决办法
    如何访问 golang.org
    GlassFish 3.1 正式版发布
    NetBeans 时事通讯(刊号 # 138 Mar 08, 2011)
    哪本书是对程序员最有影响、每个程序员都该阅读的书?
    NetBeans 时事通讯(刊号 # 138 Mar 08, 2011)
    NetBeans 时事通讯(刊号 # 137 Mar 03, 2011)
    哪本书是对程序员最有影响、每个程序员都该阅读的书?
  • 原文地址:https://www.cnblogs.com/webhmy/p/9700079.html
Copyright © 2011-2022 走看看