vue项目中弹窗拖拽、缩放功能实现过程
作者:Qredsun
文章介绍了如何在项目中实现会话窗口的拖拽和缩放功能,包括指定拖拽的窗口和区域、缩放的对象和区域,以及如何添加指定区域和改变鼠标样式
背景
在项目中有一个会话窗口,需要支持用户拖拽、缩放的功能
实现
拖拽
指定要拖拽的窗口
// 拖拽 <div ref="resizableBox" ><div class="header"></div></div>
const visible = ref(false)
const position = ref({ x: 200, y: 100 })
const emit = defineEmits(['update:visible', 'closeDialog'])
let dragging = false
let offsetX, offsetY, maxLeft, maxTop
const startDrag = (e) => {
dragging = true
offsetX = e.clientX - position.value.x
offsetY = e.clientY - position.value.y
document.body.style.userSelect = 'none'; // 防止选中文本
document.addEventListener('mousemove', onDrag)
document.addEventListener('mouseup', stopDrag)
}
const onDrag = (e) => {
if (!dragging) return
position.value.x = Math.max(0, Math.min(maxLeft,(e.clientX - offsetX)))
position.value.y = Math.max(0, Math.min(maxTop,(e.clientY - offsetY)))
console.log(maxLeft,position.value.x,maxTop,position.value.y)
}
const stopDrag = () => {
dragging = false
document.removeEventListener('mousemove', onDrag)
document.removeEventListener('mouseup', stopDrag)
}
const initDialogPosition = () => {
// 初始居中:等待 DOM 渲染后计算中心点
nextTick(() => {
const dialog = document.querySelector('.header')
if (dialog) {
const { innerWidth, innerHeight } = window
const { offsetWidth, offsetHeight } = dialog as HTMLElement
maxLeft = innerWidth - offsetWidth
maxTop = innerHeight - Math.max(560, offsetHeight)
position.value.x = maxLeft / 2
position.value.y = maxTop / 3
console.log('innerWidth', innerWidth, innerHeight)
console.log('dialog', dialog.getBoundingClientRect())
}
})
}
指定拖拽的区域
const initDialogPosition = () => {
// 初始居中:等待 DOM 渲染后计算中心点
nextTick(() => {
const dialog = document.querySelector('.header')
if (dialog) {
const { innerWidth, innerHeight } = window
const { offsetWidth, offsetHeight } = dialog as HTMLElement
maxLeft = innerWidth - offsetWidth
maxTop = innerHeight - Math.max(560, offsetHeight)
position.value.x = maxLeft / 2
position.value.y = maxTop / 3
console.log('innerWidth', innerWidth, innerHeight)
console.log('dialog', dialog.getBoundingClientRect())
}
})
}
缩放
指定缩放的对象
// 缩放 <div ref="resizableBox" ><div class="resizer" @mousedown="initResize"></div></div>
const resizableBox = ref<HTMLElement | null>(null);
function initResize(e: MouseEvent) {
const box = resizableBox.value;
if (!box) return;
const startX = e.clientX;
const startY = e.clientY;
const startWidth = box.offsetWidth;
const startHeight = box.offsetHeight;
function onMouseMove(event: MouseEvent) {
const newWidth = Math.max(400, startWidth + (event.clientX - startX));
const newHeight = Math.max(560, startHeight + (event.clientY - startY));
box.style.width = `${newWidth}px`;
box.style.height = `${newHeight}px`;
}
function onMouseUp() {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
}
也可以添加指定区域,实现鼠标样式转变
.resizer {
width: 14px;
height: 14px;
position: absolute;
right: 0;
bottom: 0;
cursor: se-resize;
z-index: 10;
border-radius: 2px;
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
