import { createApp } from 'vue' import App from './App.vue' import Icon from '@/components/icon.vue' import 'virtual:svg-icons-register' const app = createApp(App) // 自定义拖拽指令 app.directive('drag', (el) => { const oDiv = el // 当前元素 el.style.pointerEvents = null // 防止触发点击事件 oDiv.onmousedown = (e: { clientX: number; clientY: number }) => { // 找父级 是否是absolute来进行移动 let target = oDiv while (window.getComputedStyle(target).position !== 'absolute' && target !== document.body) { target = target.parentElement } // 找父级 是否是relative来进行宽度计算 let targetParent = target.parentElement while (window.getComputedStyle(targetParent).position !== 'relative' && targetParent !== document.body) { targetParent = targetParent.parentElement } document.onselectstart = () => { return false } // 鼠标按下,计算当前元素距离可视区的距离 const disX = e.clientX - target.offsetLeft const disY = e.clientY - target.offsetTop const cW = +window.getComputedStyle(target).width.replace('px', '') const cH = +window.getComputedStyle(target).height.replace('px', '') const maxW = +window.getComputedStyle(targetParent).width.replace('px', '') const maxH = +window.getComputedStyle(targetParent).height.replace('px', '') document.onmousemove = e => { // 通过事件委托,计算移动的距离 // 因为浏览器里并不能直接取到并且使用clientX、clientY,所以使用事件委托在内部做完赋值 el.style.pointerEvents = 'none' const l = e.clientX - disX const t = e.clientY - disY const cl = maxW - cW const ct = maxH - cH // 计算移动当前元素的位置,并且给该元素样式中的left和top值赋值 target.style.left = (l < 0 ? 0 : l > cl ? cl : l) + 'px' target.style.top = (t < 0 ? 0 : t > ct ? ct : t) + 'px' } document.onmouseup = e => { el.style.pointerEvents = null document.onmousemove = null document.onmouseup = null document.onselectstart = null } // return false不加的话可能导致黏连,拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效 return false } }) app.component('Icon', Icon) app.mount('#app')