一、背景
公司最近在做的一个Ant Design Vue项目,其中的某个功能页面的modal弹出框遮挡了页面的部分内容,所以需要这个modal能够用鼠标拖拽到任意位置。
二、功能实现
项目的modal如下图,需要用鼠标按住标题区域可以拖拽。
首先查一下Ant Design Vue的官方文档,发现并没有提供modal的拖拽功能,所以只能自己动手开发。modal的代码如下:
<a-modal v-model:visible="visible" title="新增表格" @ok="handleOk">
</a-modal>
为了看得清楚,我隐去了modal内部的代码,这个代码非常简单,如果直接在a-modal标签上添加鼠标事件是行不通的,因为用浏览器的F12观察一下就会发现,其内部结构并不简单,如下图:
画红框的部分是a-modal转化为纯html后的代码,如果要用鼠标按住标题区域拖拽,我想应该在其中的class为ant-modal-header的div上做文章。
第一步,先在 class为ant-modal-header的div上加个鼠标按下事件,代码如下:
setTimeout(()=>{
$('.ant-modal-header').on('mousedown',(e)=>{
this.startPosition.x = e.pageX
this.startPosition.y = e.pageY
this.startPosition.offsetX = e.offsetX
this.startPosition.offsetY = e.offsetY
this.isMovedown=true
})
},500)
这段代码要在modal弹出后,延迟500毫秒执行,因为需要等class为ant-modal-header的div完全初始化完成后,才能加入鼠标事件,否则无效,这里面用到了jquery,其中的一些属性定义如下:
data () {
return {
isMovedown: false,
startPosition: { x: 0, y: 0, offsetX: 0, offsetY: 0 },
}
},
isMovedown用来判断鼠标是否按下,startPosition记录鼠标按下时的位置。
第二步,在页面监听鼠标移动和松开事件
document.body.addEventListener('mousemove', (e) => {
if (this.isMovedown) {
if (
e.x - this.startPosition.x > 10 ||
e.y - this.startPosition.y > 10 ||
e.x - this.startPosition.x < -10 ||
e.y - this.startPosition.y < -10
) {
let w=$('.ant-modal-content').width();
let h=$('.ant-modal-content').height();
$('.ant-modal-content').css({
left: e.pageX - this.startPosition.offsetX-(document.body.clientWidth-w)/2 + 'px',
top: e.pageY -(document.body.clientHeight-h)/2 + 'px'
})
}
}
})
document.body.addEventListener('mouseup', (e) => {
this.isMovedown = false
})
其中$('.ant-modal-content')代表modal的整个窗体,如下图
因为是要让整个modal移动,并不是只让标题区域移动,所以具体的位置操作需要放在modal的整个窗体上。下图是经过鼠标拖拽后的样子