ant design vue的弹窗组件没有移动和调整大小功能,使用起来略有不便,根据网上搜索到的代码示例进行了完善,实现该功能。以防忘记,记录如下:
拖拽移动
弹框拖拽移动的功能可以参照ant design vue的最后一个示例
对话框 Modal - Ant Design Vue (antdv.com)
拖拽宽高变化
拖拽宽高变化功能代码如下:
<!--其他参照antdv官网的modal的最后一个示例-->
<template #modalRender="{ originVNode }" v-if="moveable">
<div
:style="transformStyle"
:class="isFullScreen ? 'full-screen-content' : ''"
ref="modalRef"
>
<component :is="originVNode" />
<!--主要增加这个元素用于拖拽的时候显示能够变化的大小-->
<div class="modal-drag-position"></div>
</div>
</template>
// 弹框显示的时候,调用调整调整弹框大小的函数
// useModalDrag函数的maxHeight, maxWidth, changePosition是给modal适应当前container位置使用的,
// 如果是挂载到body上可以不用这几个参数
watch(
() => props.visible,
() => {
if (props.visible) {
nextTick(() => {
useModalDrag(modalRef, isFullScreen, maxHeight, maxWidth, changePosition);
});
}
},
);
// 浏览器size发生变化的时候也调用这个函数
window.addEventListener('resize', () => {
nextTick(() => {
useModalDrag(modalRef, isFullScreen, maxHeight, maxWidth, changePosition);
});
});
import type { Ref } from 'vue';
export const useModalDrag = (modalRef: Ref<any>, isFullScreen, maxHeight, maxWidth, callback) => {
const widthDom = modalRef.value;
const dragDom = widthDom?.closest('.ant-modal-wrap');
// const widthDom = el.closest('.ant-modal');
const widthBodyDom = widthDom?.querySelector('.ant-modal-body');
const sizeChangeDom = widthDom?.querySelector('.modal-drag-position');
const headerDom = widthDom?.querySelector('.ant-modal-header');
const footerDom = widthDom?.querySelector('.ant-modal-footer');
if (!widthDom || !dragDom || !widthBodyDom || !sizeChangeDom) return;
const minWidth = widthDom.clientWidth < 300 ? widthDom.clientWidth : 300;
const minHeight = widthDom.clientHeight < 200 ? widthDom.clientHeight : 200;
maxHeight.value = dragDom.clientHeight;
maxWidth.value = dragDom.clientWidth;
sizeChangeDom.style.width = '100%';
sizeChangeDom.style.height = '100%';
dragDom.onmousemove = function (e) {
// e.stopPropagation();
if (isFullScreen.value) return;
const rect = widthDom.getBoundingClientRect();
if (e.clientX > widthDom.clientWidth + rect.left - 10) {
widthDom.style.cursor = 'e-resize';
} else if (e.clientY > widthDom.clientHeight + rect.top - 10) {
widthDom.style.cursor = 's-resize';
} else {
widthDom.style.cursor = 'default';
widthDom.onmousedown = null;
}
if (
e.clientX > widthDom.clientWidth + rect.left - 10 &&
e.clientY > widthDom.clientHeight + rect.top - 10
) {
widthDom.style.cursor = 'se-resize';
}
dragDom.onmousedown = e => {
if (isFullScreen.value) return;
const rect = widthDom.getBoundingClientRect();
dragDom.style.userSelect = 'none';
let moveDirection = '';
const initClientHeight = widthDom.clientHeight;
let heightChange = 0;
let widthNeedChange = false;
let heightNeedChange = false;
if (
e.clientX > widthDom.clientWidth + rect.left - 10 &&
e.clientX <= widthDom.clientWidth + rect.left
) {
// 左右移动
moveDirection = 'x';
}
if (
e.clientY > widthDom.clientHeight + rect.top - 10 &&
e.clientY <= widthDom.clientHeight + rect.top
) {
// 上下移动
moveDirection = 'y';
}
if (
e.clientX > widthDom.clientWidth + rect.left - 10 &&
e.clientX <= widthDom.clientWidth + rect.left &&
e.clientY > widthDom.clientHeight + rect.top - 10 &&
e.clientY <= widthDom.clientHeight + rect.top
) {
// 上下左右移动
moveDirection = 'xy';
}
if (moveDirection == '') {
return;
}
const onMouseup = () => {
if (sizeChangeDom.style.width && widthNeedChange) {
widthDom.style.width = sizeChangeDom.style.width;
}
if (heightChange && heightNeedChange) {
// widthBodyDom.style.height = widthBodyDom.clientHeight + heightChange + 'px';
let height =
sizeChangeDom.clientHeight -
(headerDom?.clientHeight || 0) -
(footerDom?.clientHeight || 0);
const maxHeight = Number(widthBodyDom.style.maxHeight?.replace('px', '') || '0');
if (height > maxHeight) {
height = maxHeight;
sizeChangeDom.style.height =
maxHeight + (headerDom?.clientHeight || 0) + (footerDom?.clientHeight || 0) + 'px';
}
widthBodyDom.style.height = height + 'px';
callback();
}
dragDom.removeEventListener('mousemove', onMousemove);
sizeChangeDom.style.zIndex = -1;
moveDirection = '';
heightChange = 0;
widthNeedChange = false;
heightNeedChange = false;
document.onmouseup = null;
};
const onMousemove = e => {
// e.stopPropagation();
if (isFullScreen.value) return;
if (moveDirection === 'x') {
sizeChangeDom.style.zIndex = 1;
let width = e.clientX - rect.left;
width = width >= minWidth ? width : minWidth;
sizeChangeDom.style.width = width + 'px';
widthNeedChange = true;
// console.info('onMousemove', sizeChangeDom.style.width);
} else if (moveDirection === 'y') {
sizeChangeDom.style.zIndex = 1;
let height = e.clientY - rect.top;
height = height >= minHeight ? height : minHeight;
// 找到移动后的变化
heightChange = height - initClientHeight;
sizeChangeDom.style.height = height + 'px';
heightNeedChange = true;
// console.info('onMousemove', sizeChangeDom.style.height);
}
if (moveDirection === 'xy') {
sizeChangeDom.style.zIndex = 1;
let width = e.clientX - rect.left;
width = width >= minWidth ? width : minWidth;
sizeChangeDom.style.width = width + 'px';
widthNeedChange = true;
sizeChangeDom.style.zIndex = 1;
let height = e.clientY - rect.top;
height = height >= minHeight ? height : minHeight;
// 找到移动后的变化
heightChange = height - initClientHeight;
sizeChangeDom.style.height = height + 'px';
heightNeedChange = true;
}
document.onmouseup = onMouseup;
};
dragDom.onmouseup = onMouseup;
dragDom.addEventListener('mousemove', onMousemove);
};
};
};
.modal-drag-position {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.1);
z-index: -1;
}