vue实现拖拽旋转
Vue 实现拖拽旋转
核心思路
通过监听鼠标事件计算旋转角度,结合 CSS 的 transform: rotate() 实现旋转效果。需要处理 mousedown、mousemove 和 mouseup 事件,并计算元素中心点与鼠标位置的夹角变化。
实现步骤
模板部分
<template>
<div class="container">
<div
class="rotatable-element"
ref="element"
:style="{ transform: `rotate(${angle}deg)` }"
@mousedown="startRotate"
></div>
</div>
</template>
脚本部分
<script>
export default {
data() {
return {
angle: 0,
startAngle: 0,
isRotating: false,
center: { x: 0, y: 0 }
}
},
methods: {
getElementCenter(el) {
const rect = el.getBoundingClientRect()
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
}
},
calculateAngle(center, mouseX, mouseY) {
return Math.atan2(mouseY - center.y, mouseX - center.x) * 180 / Math.PI
},
startRotate(e) {
this.center = this.getElementCenter(this.$refs.element)
this.startAngle = this.calculateAngle(this.center, e.clientX, e.clientY) - this.angle
this.isRotating = true
document.addEventListener('mousemove', this.rotate)
document.addEventListener('mouseup', this.stopRotate)
},
rotate(e) {
if (!this.isRotating) return
const currentAngle = this.calculateAngle(this.center, e.clientX, e.clientY)
this.angle = currentAngle - this.startAngle
},
stopRotate() {
this.isRotating = false
document.removeEventListener('mousemove', this.rotate)
document.removeEventListener('mouseup', this.stopRotate)
}
}
}
</script>
样式部分
<style>
.rotatable-element {
width: 100px;
height: 100px;
background-color: #42b983;
cursor: grab;
user-select: none;
position: absolute;
top: 50%;
left: 50%;
transform-origin: center;
}
.container {
position: relative;
height: 300px;
border: 1px dashed #ccc;
}
</style>
优化方向
边界处理 添加角度限制逻辑,例如限制旋转范围为 0-360 度:
rotate(e) {
if (!this.isRotating) return
let currentAngle = this.calculateAngle(this.center, e.clientX, e.clientY)
this.angle = (currentAngle - this.startAngle + 360) % 360
}
性能优化
使用 requestAnimationFrame 替代直接的事件处理:
rotate(e) {
if (!this.isRotating) return
requestAnimationFrame(() => {
const currentAngle = this.calculateAngle(this.center, e.clientX, e.clientY)
this.angle = currentAngle - this.startAngle
})
}
触摸屏支持 添加触摸事件处理:
<div
@mousedown="startRotate"
@touchstart="handleTouchStart"
></div>
handleTouchStart(e) {
const touch = e.touches[0]
this.startRotate({
clientX: touch.clientX,
clientY: touch.clientY
})
}






