360° 拖动旋转的角度计算原理
简化的 正方形 div demo
专注讲清楚「点击 / 拖动如何计算角度」这个原理,没有精美 UI哦
- 中间标注中心点
- 鼠标点击或拖动时,计算当前位置相对于中心的角度
- 在页面上实时显示角度
代码示例(原生 HTML + JS)
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>角度计算原理 Demo</title>
<style>body { display:flex;align-items:center;justify-content:center;height:100vh;margin:0;font-family:sans-serif; }.box {width:300px; height:300px;border:2px dashed #888;position:relative;background:#f9f9f9;}.center {position:absolute;left:50%; top:50%;transform:translate(-50%,-50%);width:8px; height:8px;background:red; border-radius:50%;}.dot {position:absolute;width:10px; height:10px;background:blue; border-radius:50%;transform:translate(-50%,-50%);pointer-events:none;}.info {margin-top:20px; font-size:16px; text-align:center;}
</style>
</head>
<body><div class="wrap"><div class="box" id="box"><div class="center"></div><div class="dot" id="dot"></div></div><div class="info" id="info">点击或拖动蓝点,显示角度</div></div><script>
(function(){const box = document.getElementById('box');const dot = document.getElementById('dot');const info = document.getElementById('info');let dragging = false;function computeAngle(evt){const rect = box.getBoundingClientRect();const cx = rect.left + rect.width/2;const cy = rect.top + rect.height/2;const dx = evt.clientX - cx;const dy = evt.clientY - cy;// atan2: 右方为0°,逆时针为正。我们希望0°在正上方,顺时针为正。let raw = Math.atan2(dy, dx) * 180 / Math.PI;let angle = (raw + 450) % 360; return {angle, x:evt.clientX, y:evt.clientY};}box.addEventListener('mousedown', e=>{dragging = true;update(e);});window.addEventListener('mousemove', e=>{if(dragging) update(e);});window.addEventListener('mouseup', ()=> dragging=false);box.addEventListener('click', e=>{update(e);});function update(e){const {angle, x, y} = computeAngle(e);dot.style.left = (x - box.getBoundingClientRect().left) + 'px';dot.style.top = (y - box.getBoundingClientRect().top) + 'px';info.textContent = "角度: " + angle.toFixed(1) + "°";}
})();
</script>
</body>
</html>
工作原理
-
取中心点坐标
const cx = rect.left + rect.width/2; const cy = rect.top + rect.height/2;
-
求向量 (dx, dy)
const dx = evt.clientX - cx; const dy = evt.clientY - cy;
-
用 atan2 计算角度
-
Math.atan2(dy, dx)
→ 返回弧度,范围-π ~ π
,0° 在右侧,逆时针为正 -
转换到度数并修正到「0° 在正上方,顺时针递增」:
let raw = Math.atan2(dy, dx) * 180 / Math.PI; let angle = (raw + 450) % 360;
-
-
实时显示角度,同时让蓝点跟随鼠标。