通过拖拽动态调整div的大小

最近遇到一个需求,页面展示两块内容,需要通过拖拽可以动态改变大小,如下图:
请添加图片描述

  • 实现思路:其实就是改变div样式的width,本质上就是Dom操作。

  • 完整代码:(基于vue2项目实践)

<template><div class="box" ref="boxRef"><div class="left" ref="leftRef">左侧内容,默认展示30%,默认最小宽度200px</div><div class="resize" ref="resizeRef"></div><div class="right" ref="rightRef">右侧内容,默认展示70%,默认最小宽度200px</div></div>
</template><script>
export default {data() {return {};},mounted() {this.handleResize();},methods: {handleResize(leftMinWidth = 200, rightMinWidth = 200) {// 获取Dom节点const boxDom = this.$refs.boxRef,leftDom = this.$refs.leftRef,resizeDom = this.$refs.resizeRef,rightDom = this.$refs.rightRef;resizeDom.onmousedown = e => {const startX = e.clientX; // 记录坐标起始位置leftDom.left = leftDom.offsetWidth; // 左边元素起始宽度document.onmousemove = e => {const endX = e.clientX; // 鼠标拖动的终止位置let moveLen = leftDom.left + (endX - startX); // 移动的距离 =  endX - startX,左边区域最后的宽度 = resizeDom.left + 移动的距离const maxWidth = boxDom.clientWidth - resizeDom.offsetWidth; // 左右两边区域的总宽度 = 外层容器宽度 - 中间区域拖拉框的宽度// 限制左边区域的最小宽度为 leftMinWidthif (moveLen < leftMinWidth) {moveLen = leftMinWidth;}// 右边区域最小宽度为 rightMinWidthif (moveLen > maxWidth - rightMinWidth) {moveLen = maxWidth - rightMinWidth;}leftDom.style.width = (moveLen / maxWidth) * 100 + "%"; // 设置左边区域的宽度,通过换算为百分比的形式,实现窗体放大缩小自适应rightDom.style.width = ((maxWidth - moveLen) / maxWidth) * 100 + "%"; // 右边区域 = 总大小 - 左边宽度 - 拖动条宽度};document.onmouseup = () => {document.onmousemove = null;document.onmouseup = null;resizeDom.releaseCapture && resizeDom.releaseCapture(); // 鼠标捕获释放};resizeDom.setCapture && resizeDom.setCapture(); // 启用鼠标捕获return false;};}}
};
</script><style lang="less" scoped>
.box {width: 100%;height: 300px;display: flex;
}
.left {width: 30%;background-color: #f1eab3;border: 1px solid #dcdfe6;
}
.resize {position: relative;width: 5px;cursor: col-resize;background-size: cover;background-position: center;&:hover {background-color: #45a3ff;}
}
.right {width: 70%;background-color: #b5ef8f;border: 1px solid #dcdfe6;
}
</style>
  • 扩展:同时支持上下/左右拖拽
    请添加图片描述

  • 实现原理和左右拖拽是一样的,只不过改变的样式是divheight

  • 完整代码如下:

<template><div class="box" ref="boxRef" id="box"><div class="left" ref="leftRef">左侧,默认width=30%,minWidth=200px</div><div class="resize" ref="resizeRef"></div><div class="right" ref="rightRef"><div class="top" ref="topRef">右侧,默认width=70%,minWidth=200px,头部区域,默认minHeight=50px</div><div class="resizeY" ref="resizeYRef"></div><div class="content" ref="contentRef">右侧,默认width=70%,minWidth=200px,内容区域,默认minHeight=50px</div></div></div>
</template><script>
export default {data() {return {};},mounted() {this.handleResize();this.handleYResize();},methods: {handleResize(leftMinWidth = 200, rightMinWidth = 200) {// 获取Dom节点const boxDom = this.$refs.boxRef,leftDom = this.$refs.leftRef,resizeDom = this.$refs.resizeRef,rightDom = this.$refs.rightRef;resizeDom.onmousedown = e => {const startX = e.clientX; // 记录坐标起始位置leftDom.left = leftDom.offsetWidth; // 左边元素起始宽度document.onmousemove = e => {const endX = e.clientX; // 鼠标拖动的终止位置let moveLen = leftDom.left + (endX - startX); // 移动的距离 =  endX - startX,左边区域最后的宽度 = resizeDom.left + 移动的距离const maxWidth = boxDom.clientWidth - resizeDom.offsetWidth; // 左右两边区域的总宽度 = 外层容器宽度 - 中间区域拖拉框的宽度// 限制左边区域的最小宽度为 leftMinWidthif (moveLen < leftMinWidth) {moveLen = leftMinWidth;}// 右边区域最小宽度为 rightMinWidthif (moveLen > maxWidth - rightMinWidth) {moveLen = maxWidth - rightMinWidth;}leftDom.style.width = (moveLen / maxWidth) * 100 + "%"; // 设置左边区域的宽度,通过换算为百分比的形式,实现窗体放大缩小自适应rightDom.style.width = ((maxWidth - moveLen) / maxWidth) * 100 + "%"; // 右边区域 = 总大小 - 左边宽度 - 拖动条宽度};document.onmouseup = () => {document.onmousemove = null;document.onmouseup = null;resizeDom.releaseCapture && resizeDom.releaseCapture(); // 鼠标捕获释放};resizeDom.setCapture && resizeDom.setCapture(); // 启用鼠标捕获return false;};},handleYResize(minTopHeight = 50, minContentHeight = 50) {const boxDom = this.$refs.boxRef,topDom = this.$refs.topRef,resizeDom = this.$refs.resizeYRef,contentDom = this.$refs.contentRef;resizeDom.onmousedown = e => {const startY = e.clientY;resizeDom.top = resizeDom.offsetHeight;document.onmousemove = e => {const endY = e.clientY;let moveLen = resizeDom.top + (endY - startY);const maxHeight = boxDom.clientHeight - resizeDom.offsetHeight;if (moveLen < minTopHeight) {moveLen = minTopHeight;}if (moveLen > maxHeight - minContentHeight) {moveLen = maxHeight - minContentHeight;}topDom.style.height = (moveLen / maxHeight) * 100 + "%";contentDom.style.height =((maxHeight - moveLen) / maxHeight) * 100 + "%";};document.onmouseup = () => {document.onmousemove = null;document.onmouseup = null;resizeDom.releaseCapture && resize.releaseCapture();};resizeDom.setCapture && resizeDom.setCapture();return false;};}}
};
</script><style lang="less" scoped>
.box {display: flex;width: 100%;height: 300px;
}
.left {width: 30%;background-color: #f1eab3;border: 1px solid #dcdfe6;
}
.resize {position: relative;width: 3px;height: 100%;cursor: col-resize;background-size: cover;background-position: center;&:hover {background-color: #45a3ff;}
}
.right {width: 70%;// background-color: #b5ef8f;// border: 1px solid #dcdfe6;overflow: hidden;.top {height: 20%;background-color: #b5ef8f;border: 1px solid #dcdfe6;}.resizeY {position: relative;height: 3px;cursor: row-resize;&:hover {background-color: #45a3ff;}}.content {height: 80%;background: #abc8ea;border: 1px solid #dcdfe6;}
}
</style>

知识点

1、属性:clientWidth / offsetWidth

clientWidth只读属性,返回元素的内部宽度,该属性包括内边距,但不包括垂直滚动条(如果有)、边框和外边距。

offsetWidth 只读属性,返回元素的布局宽度。该属性包含元素的边框、水平线上的内边距、竖直方向滚动条(如果有的话)、以及CSS设置的宽度(width)值。

例如:一个有滚动条的div
在这里插入图片描述
(clientWidth) 205 = 185(实际width) + 10 (padding) + 10 (padding)
(offsetWidth) 240 = 185(实际width) + 10 (padding) + 10 (padding) + 10 (border) + 10 (border) + 15 (scrollWidth)

2、方法:setCapture() / releaseCapture()

调用SetCapture()函数后,能够捕获鼠标相关事件:onmousedown、onmouseup、onmousemove、onclick、ondblclick、onmouseover和onmouseout,一般使用onmousemoveonmouseup两个事件。

当不再需要继续获得鼠标消息就要应该调用releaseCapture()释放掉,否则别的线程想调用就会失败。所以:setCapture()releaseCapture()必须成对呈现!

3、 鼠标事件

事件名称含义
mousedown鼠标按下
mouseup鼠标释放
click左键单击
dbclick左键双击
mousemove鼠标移动
mouseover鼠标经过
mouseout鼠标滑出
mouseenter鼠标进入
mouseleave鼠标离开
contextmenu右键菜单

1)执行顺序:mousedown => mouseup => click
2)mouseover 和 mouseout子元素也会触发,可以冒泡触发。mouseenter 和mouseleave是针对侦听的对象触发,阻止了冒泡。
3)阻止鼠标的默认事件

e.preventDefault()
e.returnValue = false; // IE8 及以下兼容写法
return false; // IE兼容写法,只用作on事件阻止默认事件
  • 事件对象属性:clientX / clientY 点击位置距离当前body可视区域的x,y 坐标。

4、鼠标样式

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/825779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第 7 章 导航实现(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 准备工作 请先安装相关的ROS功能包&#xff1a; 安装 gmapping 包(用于构建地图)&#xff1a; sudo apt inst…

爬虫机试题-爬取新闻网站

之前投简历时遇到了这样的一个笔试。本以为会是数据结构算法之类的没想到直接发了一个word直接提需求&#xff0c;感觉挺有意思就写了这篇文章&#xff0c;感兴趣的朋友可以看看。 拿到urllist 通过分析页面结构我们得以知道&#xff0c;这个页面本身没有新闻信息&#xff0c;是…

比特币叙事大转向

作者&#xff1a;David Lawant 编译&#xff1a;秦晋 要理比特币解减半动态&#xff0c;最关键的图表是下面这张&#xff0c;而不是价格图表。它显示了自 2012 年以来&#xff0c;矿业总收入与比特币现货交易量的比例&#xff0c;并标注了三个减半日期。 虽然矿工仍然是比特币生…

OpenHarmony图像解码库—stb-image [GN编译]

简介 stb_image主要是C/C实现的图像解码库。 下载安装 直接在OpenHarmony-SIG仓中搜索stb-image并下载。 使用说明 以OpenHarmony 3.1 Beta的rk3568版本为例 库代码存放路径&#xff1a;./third_party/stb-image 修改添加依赖的编译脚本&#xff0c;路径&#xff1a;/devel…

编程入门(五)【Visual Studio Code安装与C/C++语言运行】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 前言VScode安装与环境配置编写第一个C语言程序总结 前言 经过了前面对计算机…

mars3d实现禁止地图移动,禁止地图左右平移,但是鼠标可以移动的效果。

new mars3d.layer.GeoJsonLayer({渲染后实现鼠标左键按住不释放拖动时&#xff0c;地图不跟着拖动效果 当前问题&#xff1a; 1.在map初始化&#xff0c;或者是加载效果的时候&#xff0c;整个地球的场景都是一样的。 如果鼠标左键按住不释放&#xff0c;在屏幕上拖动的时候…

还在 MySQL 中使用枚举?小心有坑~

为什么使用枚举 限定值的取值范围&#xff0c;比如性别&#xff08;男&#xff0c;女&#xff0c;未知&#xff09;等。 枚举类型使用陷阱 1.超级不推荐在mysql中设置某一字段类型为enum&#xff0c;但是存的值为数字&#xff0c;比如‘0’&#xff0c;‘1’&#xff0c;‘2…

软考135-上午题-【软件工程】-软件配置管理

备注&#xff1a; 该部分考题内容在教材中找不到。直接背题目 一、配置数据库 配置数据库可以分为以下三类&#xff1a; (1) 开发库 专供开发人员使用&#xff0c;其中的信息可能做频繁修改&#xff0c;对其控制相当宽松 (2) 受控库 在生存期某一阶段工作结束时发布的阶段产…

【算法】深度优先遍历(DFS)算法详解与实现

文章目录 1.算法原理2. 常见的深度优先遍历方式3. 代码实现总结 深度优先遍历&#xff08;DFS&#xff09;是一种常用的树或图的遍历算法&#xff0c;它通过尽可能深地搜索树或图的分支&#xff0c;直到路径上的所有节点都被访问完毕&#xff0c;然后再回溯到上一层&#xff0c…

什么是云渲染?云渲染平台怎么使用?云渲染怎么收费?

什么是云渲染&#xff1f; 云渲染是一种利用云计算技术提供的云端服务&#xff0c;用户可以将本地任务递交到远程服务器上&#xff0c;由远程计算集群协调和完成渲染&#xff0c;并将结果返回本地&#xff0c;最后用户可以在本地下载渲染结果。 而实时云渲染则是云渲染的一种…

python入门之简洁安装VS保姆版安装(含虚拟环境)

11、保姆版安装 Anoconda安装&#xff08;python的一个发行版本&#xff09; 优点&#xff1a;集成了许多关于python科学计算的第三方库&#xff0c;保姆级别 下载&#xff1a;www.anaconda.com/download/ 版本默认64位&#xff0c;py37 √&#xff1a;add anaconda to my…

OCP Java17 SE Developers 复习题14

答案 C. Since the question asks about putting data into a structured object, the best class would be one that deserializes the data. Therefore, ObjectInputStream is the best choice, which is option C. ObjectWriter, BufferedStream, and ObjectReader are no…

可视化看板有那么多应用场景,该如何快速搭建?可视化工具该如何选择?

在当今的信息化时代&#xff0c;数据已经成为了现代决策的核心。无论是企业战略规划、运营管理&#xff0c;还是个人生活决策&#xff0c;数据都扮演着至关重要的角色。随着数据分析技术和工具的不断进步&#xff0c;数据在决策中的作用将变得更加突出&#xff0c;对组织和个人…

代码随想录算法训练营第三十六天|435. 无重叠区间,763.划分字母区间,56. 合并区间

题目&#xff1a;435. 无重叠区间 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi]。返回需要移除区间的最小数量&#xff0c;使剩余区间互不重叠。 题目链接/讲解链接&#xff1a; https://programmercarl.com/0435.%E6%97%A0%E9%87%8D%E5%8F%A0…

密文字段模糊检索方案

代码地址: https://github.com/zuiyu-main/EncryptDemo https://mp.weixin.qq.com/s/cXOg1tiMtJz2eibDZmXHUQ 在个别特殊领域中&#xff0c;数据的安全问题是非常的重要的&#xff0c;所以需要数据库存储的数据是需要加密存储的。所以也就引申出来本文这个问题&#xff0c;加密…

【每日刷题】Day7

【每日刷题】Day7 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 2. 203. 移除链表元素 - 力扣&#xff08;…

重磅!Meta 发布 Llama 3,前所未有的强大功能和多模态能力|TodayAI

Meta今日宣布推出其最新一代尖端开源大型语言模型Llama 3。该模型预计很快将在多个领先的云服务平台上线&#xff0c;包括AWS、Databricks、Google Cloud、Hugging Face、Kaggle、IBM WatsonX、Microsoft Azure、NVIDIA NIM和Snowflake。 Llama 3模型得到了AMD、AWS、Dell、In…

【深度学习】yolov5目标检测学习与调试

2024.4.15 -2024.4.16 完结 0.准备&&补充知识点 yolo检测算法可以实现目标检测、分割和分类任务。 项目仓库地址&#xff1a;https://github.com/ultralytics/yolov5 跟练视频&#xff1a;目标检测 YOLOv5 开源代码项目调试与讲解实战 lux下载视频神器&#xff1a;h…

2W 3KVDC 隔离 稳压单输出 DC/DC 电源模块——TPK-SAR 系列介绍

TPK-SAR系列产品是专门针对PCB上分布式电源系统中需要与输入电源隔离且输出精度要求较高的电源应用场合而设计。该产品适用于&#xff1b;1&#xff09;输入电源的电压变化≤5%&#xff1b;2&#xff09;输入输出之前要求隔离电压≥3000VDC&#xff1b;3&#xff09;对输出电压…

idea新建一个springboot项目

本文分为几个部分&#xff0c; 首先是在idea中新建项目&#xff0c; 然后是配置 项目的目录&#xff08;新建controller、service、dao等&#xff09;&#xff0c; 然后是自定义的一些工具类&#xff08;比如启动后打印地址等&#xff09;。 1.、创建篇 新建项目&#xff0…