记录一下vue项目实现el-popover弹窗拖拽以及拖动边框实现弹框拖大拖小。旨在记录,不足之处请多多指教。
1、popover弹窗拖拽的实现
具体实现的步骤如下:
//自定义指令,名为"popover",用于实现拖拽功能,要使用的组件直接v-popover
Vue.directive('popover', {
bind(el, binding, vnode, oldVnode) {
// 1、在bind钩子函数中获取弹窗标题栏元素(dialogHeaderEl)、弹窗底部元素(dialogFootEl)和弹窗内容元素(dragDom)。
const dialogHeaderEl = el.querySelector('.el-pagination'); // 获取弹窗标题栏元素
const dragDom = el.querySelector('.el-popover'); // 获取弹窗内容元素
const that=vnode.context;
// 2、判断是否成功获取到弹窗内容元素,若未获取到则不绑定拖拽功能。
if(!dragDom) return; // 如果没有找到弹窗内容元素,则不绑定拖拽
// 3、获取弹窗内容元素的样式属性(sty),包括位置等信息。
// 获取弹窗内容元素的样式属性
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
// 4、定义moveDown函数,该函数用于处理鼠标按下事件,实现拖拽效果。
const moveDown= (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
// 获取到的值带px 正则匹配替换
let styL, styT;
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if(sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
}else {
styL = +sty.left.replace(/\px/g, '');
styT = +sty.top.replace(/\px/g, '');
};
// 5、在document.onmousemove事件处理函数中计算当前元素的移动距离,并限制移动范围在窗口可视区域内。
document.onmousemove = function (e) {
// 通过事件委托,计算移动的距离
let l = e.clientX - disX + styL;
let t = e.clientY - disY + styT;
// 设置边界限制
let minL=-((document.documentElement.clientWidth-dragDom.offsetWidth)*0.5+dragDom.offsetWidth-50)
let maxL=(document.documentElement.clientWidth-dragDom.offsetWidth)*0.5+dragDom.offsetWidth-50
let minT=-document.documentElement.clientHeight*0.1
let maxT=document.documentElement.clientHeight - dragDom.offsetHeight-document.documentElement.clientHeight*0.1+dragDom.offsetHeight-50
if (l <= minL) {
l = minL
} else if (l >=maxL ){
l = maxL
}
if (t <=minT ) {
t = minT;
} else if (t >= maxT){
t = maxT
}
t = t > minT ? t : minT;
// 移动当前元素
dragDom.style.left = `${l}px`;
dragDom.style.top = `${t}px`;
//将此时的位置传出去
//binding.value({x:e.pageX,y:e.pageY})
};
// 6、在document.onmouseup事件处理函数中清除事件监听,结束拖拽操作。
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
}
// 7、将moveDown函数绑定到弹窗标题栏元素的onmousedown事件上,当鼠标按下标题栏时触发拖拽。
dialogHeaderEl.onmousedown=moveDown;
}
})
2、popover弹窗拖拽调整大小功能的实现
// 自定义指令名为"popoverDragWidth"
Vue.directive('popoverDragWidth', {
bind(el, binding, vnode, oldVnode) {
// 定义最小高度和最小宽度
const minH = 300;
const minW = 500;
// 定义边框大小
const borderSize = 10;
// 初始化起始位置和尺寸
let startX = 0;
let startY = 0;
let startWidth = 0;
let startHeight = 0;
// 获取弹窗内容元素
const dragDom = el.querySelector('.el-popover');
// 初始化是否正在调整大小的标志
let isResizing = false;
// 获取Vue实例对象
const that = vnode.context;
// 定义垂直和水平调整大小的光标样式
const handleCursorVertical = "ns-resize";
const handleCursorHorizontal = "ew-resize";
// 设置初始光标样式为垂直调整大小
dragDom.style.cursor = 'ns-resize';
// 监听鼠标移动事件,根据光标位置确定光标样式,并修改调整大小标志
dragDom.addEventListener('mousemove', e => {
let h = dragDom.clientHeight, w = dragDom.clientWidth;
let isOnHorizontalBorder = w - e.offsetX < borderSize, isOnVerticalBorder = h - e.offsetY < borderSize;
// 根据光标位置设置光标样式
if (isOnHorizontalBorder) dragDom.style.cursor = handleCursorHorizontal;
if (isOnVerticalBorder) dragDom.style.cursor = handleCursorVertical;
if (isOnHorizontalBorder && isOnVerticalBorder) dragDom.style.cursor = 'crosshair';
if (!isOnHorizontalBorder && !isOnVerticalBorder) dragDom.style.cursor = '';
// 修改调整大小标志
if (isOnHorizontalBorder || isOnVerticalBorder) isResizing = true;
})
// 监听鼠标按下事件,保存起始位置和尺寸,并添加鼠标移动和鼠标释放事件监听器
dragDom.addEventListener("mousedown", e => {
// 获取弹窗内容元素的位置和尺寸信息
const rect = dragDom.getBoundingClientRect();
startX = e.clientX;
startY = e.clientY;
startWidth = rect.width;
startHeight = rect.height;
// 如果不处于调整大小状态,直接返回
if(!isResizing) return;
// 添加鼠标移动和鼠标释放事件监听器
document.addEventListener("mousemove", resizeWidthHeight, false);
document.addEventListener("mouseup", removeResize, false);
});
// 调整元素的宽度和高度
function resizeWidthHeight(e) {
if (!isResizing) return;
// 计算新的宽度和高度
let width = startWidth + e.clientX - startX;
let height = startHeight + e.clientY - startY;
// 如果宽度小于最小宽度,则使用最小宽度
if(width < minW) width = minW;
// 如果高度小于最小高度,则使用最小高度
if(height < minH) height = minH;
// 设置元素的新宽度和高度
dragDom.style.width = `${width}px`;
dragDom.style.height = `${height}px`;
}
// 移除调整大小事件监听器,并重置光标样式,并通过 Vue 实例传递元素新的尺寸信息
function removeResize() {
isResizing = false;
document.removeEventListener("mousemove", resizeWidthHeight, false);
document.removeEventListener("mouseup", removeResize, false);
dragDom.style.cursor = '';
// 如果存在 setTablewH 方法,则调用该方法并传递元素位置和尺寸信息
that.setTablewH && that.setTablewH(dragDom.getBoundingClientRect());
}
}
});
具体实现的步骤如下:
1、在bind钩子函数中,定义最小高度(minH)和最小宽度(minW)的值,以及边框大小(borderSize)。
2、初始化起始位置和尺寸的变量,用于记录拖拽调整大小的起始状态。
3、获取弹窗内容元素(dragDom)。
4、初始化是否正在调整大小的标志(isResizing)。
5、获取Vue实例对象(that)。
6、定义垂直和水平调整大小的光标样式(handleCursorVertical和handleCursorHorizontal)。
7、设置初始光标样式为垂直调整大小。
8、监听鼠标移动事件,根据光标位置确定光标样式,并修改调整大小标志。
9、监听鼠标按下事件,保存起始位置和尺寸,并添加鼠标移动和鼠标释放事件监听器。
10、在鼠标移动事件处理函数resizeWidthHeight中计算新的宽度和高度,并限制最小宽度和最小高度。
11、在鼠标释放事件处理函数removeResize中移除调整大小事件监听器,重置光标样式,并通过Vue实例方法setTablewH传12、递元素新的位置和尺寸信息。
本文介绍了如何在Vue项目中实现el-popover弹窗的拖拽功能和通过拖动边框改变弹窗大小的功能。通过自定义指令`popover`和`popoverDragWidth`,分别实现了弹窗的拖动及拖动边框调整大小,同时设置了拖动范围限制和最小尺寸约束。



5265

被折叠的 条评论
为什么被折叠?



