vue项目中弹窗拖拽、缩放功能实现过程

 更新时间:2025年10月25日 09:25:53   作者: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;
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue获取form表单的值示例

    vue获取form表单的值示例

    今天小编就为大家分享一篇vue获取form表单的值示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • 从Vue到Postman全面验证API接口跨域问题解决

    从Vue到Postman全面验证API接口跨域问题解决

    我们都知道跨域是同源策略导致的,域名不同、协议不同、端口号不同任意一种情况都会导致跨域,这篇文章主要介绍了从Vue到Postman全面验证API接口跨域问题,需要的朋友可以参考下
    2024-08-08
  • Vue的事件响应式进度条组件实例详解

    Vue的事件响应式进度条组件实例详解

    这篇文章主要介绍了Vue的事件响应式进度条组件的实例代码,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Vue Element前端应用开发之echarts图表

    Vue Element前端应用开发之echarts图表

    在我们做应用系统的时候,往往都会涉及图表的展示,综合的图表展示能够给客户带来视觉的享受和数据直观体验,同时也是增强客户认同感的举措之一
    2021-05-05
  • 使用vue自定义如何实现Tree组件和拖拽功能

    使用vue自定义如何实现Tree组件和拖拽功能

    这篇文章主要介绍了使用vue自定义如何实现Tree组件和拖拽功能,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Vue3数字滚动插件vue-countup-v3的使用

    Vue3数字滚动插件vue-countup-v3的使用

    vue-countup-v3 插件是一个基于 Vue3 的数字动画插件,用于在网站或应用程序中创建带有数字动画效果的计数器,本文主要介绍了Vue3数字滚动插件vue-countup-v3的使用,感兴趣的可以了解一下
    2023-10-10
  • Vue 2.0 基础详细

    Vue 2.0 基础详细

    这篇文章主要介绍了Vue 2.0 基础,具体内容有、基本语法、生命周期、路由管理Vue-Router、状态管理Vuex、Http请求库Axios,想详细了解的小伙伴请和现编一起学习下面文章内容吧
    2021-10-10
  • 关于element-ui resetFields重置方法无效问题及解决

    关于element-ui resetFields重置方法无效问题及解决

    这篇文章主要介绍了关于element-ui resetFields重置方法无效问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • electron-vite工具打包后如何通过内置配置文件动态修改接口地址

    electron-vite工具打包后如何通过内置配置文件动态修改接口地址

    使用electron-vite 工具开发项目打包完后每次要改接口地址都要重新打包,对于多环境切换或者频繁变更接口地址就显得麻烦,这篇文章主要介绍了electron-vite工具打包后通过内置配置文件动态修改接口地址实现方法,需要的朋友可以参考下
    2024-05-05
  • Vue项目通过network的ip地址访问注意事项及说明

    Vue项目通过network的ip地址访问注意事项及说明

    这篇文章主要介绍了Vue项目通过network的ip地址访问注意事项及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09

最新评论