vue实现拖拽旋转
实现拖拽旋转的基本思路
在Vue中实现拖拽旋转功能,通常需要结合鼠标事件和CSS变换。通过监听鼠标的按下、移动和释放事件,计算旋转角度并应用到目标元素上。
核心代码示例
以下是一个基于Vue 3的拖拽旋转实现示例:
<template>
<div
class="rotatable-element"
ref="element"
@mousedown="startRotate"
:style="{ transform: `rotate(${angle}deg)` }"
>
拖拽我旋转
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const angle = ref(0)
const element = ref(null)
const startAngle = ref(0)
const startPosition = ref({ x: 0, y: 0 })
const isRotating = ref(false)
const getCenter = (el) => {
const rect = el.getBoundingClientRect()
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
}
}
const getAngle = (center, position) => {
return Math.atan2(position.y - center.y, position.x - center.x) * 180 / Math.PI
}
const startRotate = (e) => {
isRotating.value = true
const center = getCenter(element.value)
startPosition.value = { x: e.clientX, y: e.clientY }
startAngle.value = getAngle(center, startPosition.value) - angle.value
document.addEventListener('mousemove', rotate)
document.addEventListener('mouseup', stopRotate)
}
const rotate = (e) => {
if (!isRotating.value) return
const center = getCenter(element.value)
const currentPosition = { x: e.clientX, y: e.clientY }
angle.value = getAngle(center, currentPosition) - startAngle.value
}
const stopRotate = () => {
isRotating.value = false
document.removeEventListener('mousemove', rotate)
document.removeEventListener('mouseup', stopRotate)
}
return { angle, element, startRotate }
}
}
</script>
<style>
.rotatable-element {
width: 200px;
height: 200px;
background-color: #42b983;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: grab;
user-select: none;
transform-origin: center;
}
</style>
关键点解析
计算旋转中心
通过getBoundingClientRect()获取元素的位置和尺寸,计算元素的中心点坐标。
角度计算
使用Math.atan2函数计算鼠标位置相对于元素中心的角度,公式为:
$$
angle = \arctan2(y - centerY, x - centerX) \times \frac{180}{\pi}
$$
事件处理
在鼠标按下时记录初始角度和位置,移动时计算新角度并更新旋转值,释放时移除事件监听。

CSS变换
通过绑定transform: rotate()样式实现视觉旋转效果,注意设置transform-origin为center确保围绕中心旋转。
优化建议
-
节流处理
对mousemove事件进行节流,避免频繁重绘导致的性能问题。 -
触摸支持
添加touchstart、touchmove和touchend事件处理,实现移动端兼容。
-
限制旋转范围
如果需要限制旋转角度,可以在计算角度时进行范围约束。 -
动画效果
添加CSS过渡效果使旋转更平滑:transition: transform 0.1s ease-out; -
组件化
将旋转逻辑封装为可复用的指令或组件,方便多处使用。






