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()
相关推荐
林太白2 分钟前
Nuxt3 功能篇
前端·javascript·后端
YuJie3 分钟前
webSocket Manager
前端·javascript
Mapmost18 分钟前
Mapmost SDK for UE5 内核升级,三维场景渲染效果飙升!
前端
Mapmost21 分钟前
重磅升级丨Mapmost全面兼容3DTiles 1.1,3DGS量测精度跃升至亚米级!
前端·vue.js·three.js
wycode27 分钟前
Promise(一)极简版demo
前端·javascript
浮幻云月28 分钟前
一个自开自用的Ai提效VsCode插件
前端·javascript
DevSecOps选型指南29 分钟前
SBOM风险预警 | NPM前端框架 javaxscript 遭受投毒窃取浏览器cookie
前端·人工智能·前端框架·npm·软件供应链安全厂商·软件供应链安全工具
__lll_37 分钟前
Docker 从入门到实战:容器、镜像与 Compose 全攻略
前端·docker
木春1 小时前
react组件化思维:高复用性 UI 设计之道
前端·react.js