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;
}

总结

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

相关文章

  • vueJs实现DOM加载完之后自动下拉到底部的实例代码

    vueJs实现DOM加载完之后自动下拉到底部的实例代码

    这篇文章主要介绍了vueJs实现DOM加载完成之后自动下拉到底部的实例代码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-08-08
  • vue3中使用props和emits并指定其类型与默认值

    vue3中使用props和emits并指定其类型与默认值

    props是Vue3中的一个重要概念,它允许我们将数据从父组件传递到子组件,下面这篇文章主要给大家介绍了关于vue3中使用props和emits并指定其类型与默认值的相关资料,需要的朋友可以参考下
    2023-04-04
  • 关于vuex状态刷新网页时数据被清空问题及解决

    关于vuex状态刷新网页时数据被清空问题及解决

    这篇文章主要介绍了关于vuex状态刷新网页时数据被清空问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • vue echarts实现柱状图动态展示

    vue echarts实现柱状图动态展示

    这篇文章主要为大家详细介绍了vue echarts实现柱状图动态展示,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • vue3实现页面跳转的示例代码

    vue3实现页面跳转的示例代码

    这篇文章给大家介绍了vue3如何实现页面跳转,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-02-02
  • vue3 可拖动的左右面板分割组件实现

    vue3 可拖动的左右面板分割组件实现

    最近在使用vue的时候,遇到一个需求,实现左右div可通过中间部分拖拽调整宽度,本文就整理一下,分享给大家,有兴趣的可以学习
    2021-06-06
  • vue结合axios实现restful风格的四种请求方式

    vue结合axios实现restful风格的四种请求方式

    这篇文章主要介绍了vue结合axios实现restful风格的四种请求方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • vue3中事件处理@click的用法详解

    vue3中事件处理@click的用法详解

    @click指令用于监听元素的点击事件,并在触发时执行相应的处理函数,在Vue3中,事件处理就可以通过@click指令来实现,下面我们就来看看如何在Vue3中处理点击事件吧
    2023-08-08
  • vue 实现通过手机发送短信验证码注册功能

    vue 实现通过手机发送短信验证码注册功能

    这篇文章主要介绍了vue 实现通过手机发送短信验证码注册功能的相关资料,需要的朋友可以参考下
    2018-04-04
  • vue定义私有过滤器和基本使用

    vue定义私有过滤器和基本使用

    这篇文章主要介绍的是 vue定义私有过滤器和基本使用,下面文章围绕vue定义私有过滤器的相关资料展开内容,需要的朋友可以参考一下,希望对大家有所帮助
    2021-11-11

最新评论