当前位置: 首页 > article >正文

Vue3实现拖拽改变元素大小

代码实现

整体页面结构通过一个 dragResize-wrapper 包含左右两个区域,左侧区域包含一个可拖拽的边界。以下是关键代码

HTML 部分
<template><div class="dragResize-wrapper"><div class="dragResize-left"><div class="resize" @mousedown="resize"></div></div><div class="dragResize-right"></div></div>
</template>
CSS 部分
<style lang="less" scoped>
.dragResize-wrapper {display: flex;width: 100vw;height: 100vh;.dragResize-left {position: relative;width: 30%;height: 100%;background-color: #1a2029;border-right: 1px solid #ccc;.resize {position: absolute;right: 0;width: 10px;height: 100%;background-color: #1a2029;}.resize:hover {cursor: e-resize;}}.dragResize-right {width: 70%;height: 100%;background-color: #472020;}
}
</style>
JavaScript 部分
<script setup>
import { ref, reactive, onMounted } from "vue";
const dragState = reactive({isDragging: false,startX: 0,leftInitialWidth: 0,minWidth: 100, // 左侧区域最小宽度限制maxWidth: 800, // 左侧区域最大宽度限制
});const resize = (e) => {dragState.isDragging = true;dragState.startX = e.clientX; // 获取鼠标按下时的 X 坐标dragState.leftInitialWidth = e.currentTarget.parentElement.offsetWidth; // 获取左侧区域初始宽度document.body.style.cursor = "e-resize"; // 设置鼠标样式为拖拽样式document.body.style.userSelect = "none"; // 禁止选中文本
};// 鼠标移动事件,执行拖拽调整宽度
const handleMouseMove = (e) => {if (!dragState.isDragging) return; // 如果没有拖拽,直接返回const deltax = e.clientX - dragState.startX; // 计算鼠标移动的距离let newWidth = dragState.leftInitialWidth + deltax; // 计算新的宽度newWidth = Math.max(dragState.minWidth,Math.min(newWidth, dragState.maxWidth)); // 限制宽度在最小和最大值之间document.querySelector(".dragResize-left").style.width = `${newWidth}px`; // 设置左侧区域的新宽度document.querySelector(".dragResize-right").style.width = `calc(100% - ${newWidth}px)`; // 设置右侧区域宽度为剩余空间
};// 鼠标松开事件,结束拖拽
const handleMouseUp = () => {if (dragState.isDragging) {dragState.isDragging = false; // 重置拖拽状态document.body.style.cursor = "default"; // 恢复鼠标样式document.body.style.userSelect = "auto"; // 恢复文本选择}
};onMounted(() => {document.addEventListener("mousemove", handleMouseMove); // 监听鼠标移动事件document.addEventListener("mouseup", handleMouseUp); // 监听鼠标松开事件
});
</script>

定义一个 dragState 对象来跟踪拖拽状态,包括是否正在拖拽、鼠标起始坐标、左侧区域初始宽度以及左右宽度限制。在 resize 函数中,设置拖拽开始时的相关状态和样式。handleMouseMove 函数根据鼠标移动距离计算新的宽度,并在一定范围内调整左右区域的宽度。handleMouseUp 函数用于结束拖拽并恢复样式。在组件挂载后添加鼠标移动和松开的事件监听。

完整实例代码

<template><div class="dragResize-wrapper"><div class="dragResize-left"><div class="resize" @mousedown="resize"></div></div><div class="dragResize-right"></div></div>
</template><script setup>
import { ref, reactive, onMounted } from "vue";
const dragState = reactive({isDragging: false,startX: 0,leftInitialWidth: 0,minWidth: 100, // 左侧区域最小宽度限制maxWidth: 800, // 左侧区域最大宽度限制
});const resize = (e) => {dragState.isDragging = true;dragState.startX = e.clientX; // 获取鼠标按下时的X坐标dragState.leftInitialWidth = e.currentTarget.parentElement.offsetWidth; // 获取左侧区域初始宽度document.body.style.cursor = "e-resize"; // 设置鼠标样式为拖拽样式document.body.style.userSelect = "none"; // 禁止选中文本
};// 鼠标移动事件,执行拖拽调整宽度
const handleMouseMove = (e) => {if (!dragState.isDragging) return; // 如果没有拖拽,直接返回const deltax = e.clientX - dragState.startX; // 计算鼠标移动的距离let newWidth = dragState.leftInitialWidth + deltax; // 计算新的宽度newWidth = Math.max(dragState.minWidth,Math.min(newWidth, dragState.maxWidth)); // 限制宽度在最小和最大值之间document.querySelector(".dragResize-left").style.width = `${newWidth}px`; // 设置左侧区域的新宽度document.querySelector(".dragResize-right").style.width = `calc(100% - ${newWidth}px)`; // 设置右侧区域宽度为剩余空间
};// 鼠标松开事件,结束拖拽
const handleMouseUp = () => {if (dragState.isDragging) {dragState.isDragging = false; //重置拖拽状态document.body.style.cursor = "default"; // 恢复鼠标样式document.body.style.userSelect = "auto"; // 恢复文本选择}
};onMounted(() => {document.addEventListener("mousemove", handleMouseMove); // 监听鼠标移动事件document.addEventListener("mouseup", handleMouseUp); // 监听鼠标松开事件
});
</script><style lang="less" scoped>
.dragResize-wrapper {display: flex;width: 100vw;height: 100vh;.dragResize-left {position: relative;width: 30%;height: 100%;background-color: #1a2029;border-right: 1px solid #ccc;.resize {position: absolute;right: 0;width: 10px;height: 100%;background-color: #1a2029;}.resize:hover {cursor: e-resize;}}.dragResize-right {width: 70%;height: 100%;background-color: #472020;}
}
</style>

http://www.lryc.cn/news/2401787.html

相关文章:

  • Spring IoC 详解:原理、实现与实战
  • 深入Java NIO:构建高性能网络应用
  • 数据分析后台设计指南:实战案例解析与5大设计要点总结
  • 深度学习之模型压缩三驾马车:基于ResNet18的模型剪枝实战(1)
  • SSH/RDP无法远程连接?腾讯云CVM及通用服务器连接失败原因与超全排查指南
  • 网络测试实战:金融数据传输的生死时速
  • 数据库系统概论(十四)详细讲解SQL中空值的处理
  • 【信创-k8s】海光/兆芯+银河麒麟V10离线部署k8s1.31.8+kubesphere4.1.3
  • [蓝桥杯]三体攻击
  • 深入解析支撑向量机(SVM):原理、推导与实现
  • 一台电脑联网如何共享另一台电脑?网线方式
  • 面试题:SQL 中如何将 多行合并为一行(合并行数据为列)?
  • MacroDroid安卓版:自动化操作,让生活更智能
  • 力提示(force prompting)的新方法
  • 【Redis实战:缓存与消息队列的应用】
  • 实验设计与分析(第6版,Montgomery著,傅珏生译) 第10章拟合回归模型10.9节思考题10.12 R语言解题
  • 基于LangChain构建高效RAG问答系统:向量检索与LLM集成实战
  • 告别局域网:实现NASCab云可云远程自由访问
  • 25_05_29docker
  • Java-IO流之缓冲流详解
  • vscode code runner 使用python虚拟环境
  • Python实现markdown文件转word
  • NLP学习路线图(十七):主题模型(LDA)
  • 深度学习之模型压缩三驾马车:基于ResNet18的模型剪枝实战(2)
  • 综采工作面电控4X型铜头连接器 conm/4x100s
  • 用ApiFox MCP一键生成接口文档,做接口测试
  • 在compose中的Canvas用kotlin显示多数据波形闪烁的问题
  • 【学习笔记】MIME
  • 【深尚想】OPA855QDSGRQ1运算放大器IC德州仪器TI汽车级高速8GHz增益带宽的全面解析
  • 单北斗定位芯片AT9880B