You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
2.2 KiB
TypeScript

1 month ago
// plugins/draggable.client.ts
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin((nuxtApp) => {
// 拖拽指令
nuxtApp.vueApp.directive('draggable', {
mounted(el, binding) {
// 只在客户端执行
if (import.meta.server) return
const triggerSelector = binding.value?.triggerSelector || '.el-dialog__header'
const dialogHeaderEl = el.querySelector(triggerSelector) as HTMLElement
const dialogEl = el.querySelector('.el-dialog') as HTMLElement
if (!dialogHeaderEl || !dialogEl) return
let isDragging = false
let offsetX = 0
let offsetY = 0
const startDrag = (e: MouseEvent) => {
isDragging = true
const rect = dialogEl.getBoundingClientRect()
offsetX = e.clientX - rect.left
offsetY = e.clientY - rect.top
dialogEl.style.cursor = 'move'
}
const onDrag = (e: MouseEvent) => {
if (!isDragging) return
const x = e.clientX - offsetX
const y = e.clientY - offsetY
// 边界限制
const maxX = window.innerWidth - dialogEl.offsetWidth
const maxY = window.innerHeight - dialogEl.offsetHeight
dialogEl.style.left = `${Math.max(0, Math.min(x, maxX))}px`
dialogEl.style.top = `${Math.max(0, Math.min(y, maxY))}px`
}
const stopDrag = () => {
isDragging = false
dialogEl.style.cursor = ''
}
dialogHeaderEl.addEventListener('mousedown', startDrag)
document.addEventListener('mousemove', onDrag)
document.addEventListener('mouseup', stopDrag)
// 清理函数
; (el as any)._dragCleanup = () => {
dialogHeaderEl.removeEventListener('mousedown', startDrag)
document.removeEventListener('mousemove', onDrag)
document.removeEventListener('mouseup', stopDrag)
}
},
unmounted(el) {
; (el as any)._dragCleanup?.()
}
})
})