web实现drag拖拽布局

这种拖拽布局功能其实在电脑操作系统或者桌面应用里面是经常使用的基础功能,只是有时候在进行web开发的时候,对这个功能需求量不够明显,但却是很好用,也很实用。能够让用户自己拖拽布局,方便查看某个区域更多内容,这一点足够吸引人的。

这里用原生实现这个特殊的拖拽布局功能,可以作为参考和学习使用。话不多说,先看看实现的静态效果和动态效果。

静态效果:

动态效果:

为了查看更佳效果,需要把源码在浏览器上运行起来。另一个值得关心的事项:案例中左右盒子是可以完全拖拽关闭的,也就是宽度为0px。实际应用中可能不需要这种效果,没关系,可以限制左右盒子的最小宽度,判断小于最小宽度就不再进行缩小即可,放大限制 也是类似的。

实现原理

想象一下,拖拽布局一般都需要两个div盒子,同时需要一个可以拖拽的class=resize盒子(以下简称resize),它们都是块元素。然后加上HTML标签和css的基础左右布局样式,大致轮廓就出来了。

到这里还没有实现拖拽resize布局逻辑,接着往下看。

拖拽resize原理分析:

当用户把鼠标移动到resize盒子上面,此时出现可以左右拖拽的标识,这个标识可以用css的cursor: w-resize来实现。

如果用户按下鼠标左键,可以监听鼠标按下事件,获得鼠标按下的startX = evt.clientX,也能获得resize相对于父元素的左偏移值offsetLeft。

复制代码
resizeBar.onmousedown(evt) {  var startX = e.clientX;  resizeBar.left = resizeBar.offsetLeft;}

如果用户按住鼠标左键开始向左或者向右拖拽,需要精确计算用户拖拽的实际距离,也是鼠标移动的实际距离。计算方式:resize的左偏移值offsetLeft+(鼠标移动实际距离 + 鼠标按下距离)= 实际移动距离movelen。​​​​​​​

复制代码
 document.onmousemove = function (e) {   var moveLen = resizeBar.left + (e.clientX - startX); }

那么,resize的左边距离移动实际距离就是这样获得的。​​​​​​​

复制代码
document.onmousemove = function (e) {   var moveLen = resizeBar.left + (e.clientX - startX);   resizeBar.style.left = moveLen + 'px';}

左边|右边盒子宽度就可以得到了。​​​​​​​

复制代码
document.onmousemove = function (e) {   var moveLen = resizeBar.left + (e.clientX - startX);   resizeBar.style.left = moveLen + 'px';   leftBox.style.width = moveLen + "px";   rightBox.style.width =    boxWidth - resizeWidth - moveLen + "px";}

到这里拖拽核心逻辑就结束了,为了更好的理解拖拽过程,于是就有了下方不怎么好看的抽象图,画的不好,多多理解。

源码贴上

HTML​​​​​​​

复制代码
<body><div class="box">    <div class="left overflow">        <p>左边盒子</p>    </div>    <div class="resize"></div>    <div class="right overflow">        <p>右边盒子</p>    </div></div></body>

CSS​​​​​​​

复制代码
<style>.box {    width: 100%;    height: 100vh;    display: flex;}.left {    background: lightblue;}.resize {    width: 10px;    height: 100%;    background-color: #399aef;    cursor: w-resize;}.right {    background: rgba(0, 0, 0, 0.4);}p {    padding: 20px;    text-align: center;    font-size: 25px;    font-weight: 600;}[class*="overflow"] {    width: 49%;    height: 100%;    overflow: hidden;}.userselect {    -webkit-user-select: none;     -moz-user-select: none;     -ms-user-select: none;     user-select: none;}</style>

JavaScript​​​​​​​​​​​​​​

复制代码
<script>function dragResize() {    var resizeBar = document.querySelector(".resize");    var leftBox = document.querySelector(".left");    var box = document.querySelector(".box");    var rightBox = document.querySelector(".right");    var resizeWidth = resizeBar.offsetWidth;    var boxWidth = box.offsetWidth;    resizeBar.onmousedown = function (e) {        var startX = e.clientX;        resizeBar.left = resizeBar.offsetLeft;
        // 鼠标拖动事件        document.onmousemove = function (e) {            var moveLen = resizeBar.left + (e.clientX - startX);            resizeBar.style.left = moveLen + 'px';            leftBox.style.width = moveLen + "px";            rightBox.style.width = boxWidth - resizeWidth - moveLen + "px";            e.target.style.cursor = "w-resize"            // 拖拽过程中,禁止选中文本            leftBox.classList.add('userselect')            rightBox.classList.add('userselect')        };
        // 鼠标松开事件        document.onmouseup = function (evt) {            document.onmousemove = null;            document.onmouseup = null;            // 清空cursor            leftBox.style.cursor = "default"            rightBox.style.cursor = "default"            leftBox.classList.remove('userselect')            rightBox.classList.remove('userselect')        };    };}dragResize()
相关推荐
摸鱼的春哥3 小时前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
念念不忘 必有回响3 小时前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
C澒3 小时前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅3 小时前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘3 小时前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
恋猫de小郭4 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅10 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端