指令
- /directives/draggable.js
js
import { nextTick } from 'vue'
// directives/draggable.js
export const draggable = {
async mounted(el, binding) {
await nextTick()
// 获取对应DOM
const dialogHeaderEl = el.querySelector('.ant-modal-header') // 类名一定要替换成自己的 我本地改了前缀
const dragDom = el.querySelector('.ant-modal') // 类名一定要替换成自己的 我本地改了前缀
dialogHeaderEl.style.cssText += ';cursor:move;'
// 获取原有属性 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = (function () {
return (dom, attr) => getComputedStyle(dom, null)[attr]
})()
dialogHeaderEl.addEventListener('mousedown', (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
const screenWidth = document.body.clientWidth // body当前宽度
const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取)
const dragDomWidth = dragDom.offsetWidth // 对话框宽度
const dragDomheight = dragDom.offsetHeight // 对话框高度
const minDragDomLeft = dragDom.offsetLeft
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
const minDragDomTop = dragDom.offsetTop
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight
// 获取到的值带px 正则匹配替换
let styL = sty(dragDom, 'left')
// 为兼容ie
if (styL === 'auto') styL = '0px'
let styT = sty(dragDom, 'top')
// console.log(styL)
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (styL.includes('%')) {
styL = Number(document.body.clientWidth) * (Number(styL.replace(/%/g, '')) / 100)
styT = Number(document.body.clientHeight) * (Number(styT.replace(/%/g, '')) / 100)
} else {
styL = Number(styL.replace(/px/g, ''))
styT = Number(styT.replace(/px/g, ''))
}
const fn = (e) => {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
let top = e.clientY - disY
// 边界处理
if (-(left) > minDragDomLeft) {
left = -(minDragDomLeft)
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft
}
if (-(top) > minDragDomTop) {
top = -(minDragDomTop)
} else if (top > maxDragDomTop) {
top = maxDragDomTop
}
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
}
document.addEventListener('mousemove', fn)
document.addEventListener('mouseup', (e) => {
document.removeEventListener('mousemove', fn)
})
return false
})
},
}
注册指令
- /main.js
js
import { draggable } from './directives/draggable'
app.directive('draggable', draggable)
使用指令
- demo.vue
html
<div ref='modalBox' v-draggable>
<a-modal
v-model:open='visible' title='编辑' ok-text='保存'
:get-container='() => $refs.modalBox'
:force-render='true'
@ok='onSave'
>
</a-modal>
</div>