/*
* @Description: 拖拽
*/
import { computed, type Ref, ref, onMounted, onUnmounted } from 'vue'
export interface Position {
x: number
y: number
}
/**
* Make elements draggable.
* @param target
* @param options
*/
export function useDraggable(
target: Ref<HTMLElement | null>,
options = {
initialValue: { x: 0, y: 0 }
}
) {
const posX = ref(options.initialValue.x)
const posY = ref(options.initialValue.y)
const isDragging = ref(false)
const mouseX = ref(0)
const mouseY = ref(0)
const startDrag = (e) => {
// 禁止内部DOM移动
if (e.target !== target.value) {
// 阻止默认行为,即禁止鼠标在内部DOM上移动
e.preventDefault()
return
}
isDragging.value = true
mouseX.value = e.clientX
mouseY.value = e.clientY
if (target.value) {
target.value.style.cursor = 'grabbing'
}
}
const stopDrag = () => {
isDragging.value = false
if (target.value) {
target.value.style.cursor = 'grab'
}
}
const handleDrag = (e) => {
if (!isDragging.value) return
const deltaX = e.clientX - mouseX.value
const deltaY = e.clientY - mouseY.value
posX.value += deltaX
posY.value += deltaY
mouseX.value = e.clientX
mouseY.value = e.clientY
}
onMounted(() => {
target.value?.addEventListener('mousedown', startDrag)
window.addEventListener('mouseup', stopDrag)
window.addEventListener('mousemove', handleDrag)
})
onUnmounted(() => {
target.value?.removeEventListener('mousedown', startDrag)
window.removeEventListener('mouseup', stopDrag)
window.removeEventListener('mousemove', handleDrag)
})
// 计算样式对象
const draggableStyle = computed(() => ({
top: `${posY.value}px`,
left: `${posX.value}px`,
cursor: isDragging.value ? 'grabbing' : 'grab'
}))
return { x: posX, y: posY, style: draggableStyle, isDragging }
}
暂无评论