ant组件的弹窗组件不支持拖拽,就很难受
项目里刚好有这个需求,就自己封装了一个
<template>
<div class="image-standard-modal"
:style="{ top: top + 'px', left: left + 'px' }"
v-show="visible"
v-on:mouseenter="onMouseEnter(true)"
v-on:mouseleave="onMouseLeave">
<div v-on:mouseenter="onMouseEnter(true)">
<div class="header"
v-on:mouseenter="onMouseEnter(true)">
<span class="title">{{ title }}</span>
<a-icon class="float-right"
style="font-size: 18px;"
type="close" />
<a-divider />
</div>
<div class="body"
v-on:mouseenter="onMouseEnter(false)">
<slot></slot>
</div>
</div>
</div>
</template>
<script lang="ts">
import {
Vue, Component, Prop, Emit,
} from 'vue-property-decorator';
import GBackstageBreadcrumb from '@/components/common/GBackstageBreadcrumb.vue';
@Component({
name: 'DragAndDropModal',
components: { BackstageBreadcrumb: GBackstageBreadcrumb },
})
export default class DragAndDropModal extends Vue {
@Prop({ default: true }) visible!: boolean;
@Prop({ default: '影像标准信息' }) title!: string;
top = 200; // 弹窗的垂直位置
left: any = '50%'; // 弹窗的水平位置
dragging = false; // 是否正在拖拽
diffX = 0; // 鼠标在弹窗内的水平偏移量
diffY = 0; // 鼠标在弹窗内的垂直偏移量
// 鼠标进入弹窗区域
handleMouseDown(event) {
event.preventDefault();
this.dragging = true;
this.diffX = event.clientX - event.target.getBoundingClientRect().left;
this.diffY = event.clientY - event.target.getBoundingClientRect().top;
}
// 鼠标移动事件
handleMouseMove(event) {
if (this.dragging) {
this.left = event.clientX - this.diffX;
this.top = event.clientY - this.diffY;
}
}
// 鼠标松开事件
handleMouseUp() {
this.dragging = false;
}
// 鼠标进入弹窗区域注册监听鼠标
onMouseEnter(type) {
console.log(type);
if (type) {
document.addEventListener('mousedown', this.handleMouseDown);
document.addEventListener('mousemove', this.handleMouseMove);
document.addEventListener('mouseup', this.handleMouseUp);
} else {
// 鼠标离开弹窗区域取消监听鼠标
this.onMouseLeave();
}
}
// 鼠标离开弹窗区域取消监听鼠标
onMouseLeave() {
if (this.dragging) {
return;
}
document.removeEventListener('mousedown', this.handleMouseDown);
document.removeEventListener('mousemove', this.handleMouseMove);
document.removeEventListener('mouseup', this.handleMouseUp);
}
}
</script>
<style scoped lang='less'>
// 分割线
.ant-divider-horizontal {
margin: 24px 0 0 0 !important;
}
.image-standard-modal{
position: fixed; // 定位到最外层
top: 100;
left: 100;
min-width: 400px;
z-index: 1000;
padding: 98px 24px 24px 24px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.8);
.header {
position: absolute;
top: 0;
left: 0;
padding: 24px 24px 0 24px;
background-color: white;
width: 100%;
.title {
font-size: 16px;
font-weight: 600;
color: #333;
}
}
.body{
min-height: 200px;
max-height: 70vh;
}
}
</style>
<template>
<div class="image-standard-modal"
:style="{ top: top + 'px', left: left + 'px' }"
v-show="visible"
v-on:mouseenter="onMouseEnter(true)"
v-on:mouseleave="onMouseLeave">
<div v-on:mouseenter="onMouseEnter(true)">
<div class="header"
v-on:mouseenter="onMouseEnter(true)">
<span class="title">{{ title }}</span>
<a-icon class="float-right"
style="font-size: 18px;"
type="close" />
<a-divider />
</div>
<div class="body"
v-on:mouseenter="onMouseEnter(false)">
<slot></slot>
</div>
</div>
</div>
</template>
<script lang="ts">
import {
Vue, Component, Prop, Emit,
} from 'vue-property-decorator';
import GBackstageBreadcrumb from '@/components/common/GBackstageBreadcrumb.vue';
@Component({
name: 'DragAndDropModal',
components: { BackstageBreadcrumb: GBackstageBreadcrumb },
})
export default class DragAndDropModal extends Vue {
@Prop({ default: true }) visible!: boolean;
@Prop({ default: '影像标准信息' }) title!: string;
top = 200; // 弹窗的垂直位置
left: any = '50%'; // 弹窗的水平位置
dragging = false; // 是否正在拖拽
diffX = 0; // 鼠标在弹窗内的水平偏移量
diffY = 0; // 鼠标在弹窗内的垂直偏移量
// 鼠标进入弹窗区域
handleMouseDown(event) {
event.preventDefault();
this.dragging = true;
this.diffX = event.clientX - event.target.getBoundingClientRect().left;
this.diffY = event.clientY - event.target.getBoundingClientRect().top;
}
// 鼠标移动事件
handleMouseMove(event) {
if (this.dragging) {
this.left = event.clientX - this.diffX;
this.top = event.clientY - this.diffY;
}
}
// 鼠标松开事件
handleMouseUp() {
this.dragging = false;
}
// 鼠标进入弹窗区域注册监听鼠标
onMouseEnter(type) {
console.log(type);
if (type) {
document.addEventListener('mousedown', this.handleMouseDown);
document.addEventListener('mousemove', this.handleMouseMove);
document.addEventListener('mouseup', this.handleMouseUp);
} else {
// 鼠标离开弹窗区域取消监听鼠标
this.onMouseLeave();
}
}
// 鼠标离开弹窗区域取消监听鼠标
onMouseLeave() {
if (this.dragging) {
return;
}
document.removeEventListener('mousedown', this.handleMouseDown);
document.removeEventListener('mousemove', this.handleMouseMove);
document.removeEventListener('mouseup', this.handleMouseUp);
}
}
</script>
<style scoped lang='less'>
// 分割线
.ant-divider-horizontal {
margin: 24px 0 0 0 !important;
}
.image-standard-modal {
position: fixed; // 定位到最外层
top: 100;
left: 100;
min-width: 400px;
z-index: 1000;
padding: 98px 24px 24px 24px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.8);
.header {
position: absolute;
top: 0;
left: 0;
padding: 24px 24px 0 24px;
background-color: white;
width: 100%;
.title {
font-size: 16px;
font-weight: 600;
color: #333;
}
}
.body {
min-height: 150px;
max-height: 70vh;
}
}
</style>
// 引入
import DragAndDropModal from '@/map/DragAndDropModal.vue';
// 注册
@Component({
name: 'OpenLayerMapRightLayout',
components: {
DragAndDropModal,
},
})
// 使用
<DragAndDropModal>可拖拽弹窗</DragAndDropModal>