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
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?.()
|
||
|
|
}
|
||
|
|
})
|
||
|
|
})
|