深圳幻海软件技术有限公司 欢迎您!

05#Web 实战:可拖拽的侧边栏

2023-03-02

效果演示图可拖拽的左、右侧边栏的使用情况还是挺多的,博客园后台管理的左侧边栏就可以拖拽哟!效果演示如下图:HTML代码<divclass="container"><divclass="left"><divclass="resize-bar"></div&gt

效果演示图

可拖拽的左、右侧边栏的使用情况还是挺多的,博客园后台管理的左侧边栏就可以拖拽哟!效果演示如下图:

HTML 代码

<div class="container">
  <div class="left">
    <div class="resize-bar"></div>
  </div>
  <div class="right">
    <div class="resize-bar"></div>
  </div>
</div>

CSS 代码

html,
body {
  display: flex;
  justify-content: center;
  align-items: center;
  align-content: center;
  padding: 0 !important;
  margin: 0 !important;
}

.container {
  width: 80vw;
  height: 100vh;
  display: flex;
  justify-content: space-between;
  align-items: center;
  align-content: center;
}

.left {
  position: relative;
  width: 100px;
  height: 100%;
  background-color: rgb(160, 212, 233);
}

.left .resize-bar {
  position: absolute;
  top: 0;
  left: 100px;
  width: 3px;
  height: 100%;
  opacity: 0;
}

.left .resize-bar:hover {
  cursor: col-resize;
  opacity: 1;
  background-color: rgb(210, 85, 50);
}

.right {
  position: relative;
  width: 100px;
  height: 100%;
  background-color: rgb(36, 107, 214);
}

.right .resize-bar {
  position: absolute;
  top: 0;
  right: 100px;
  width: 3px;
  height: 100%;
  opacity: 0;
}

.right .resize-bar:hover {
  cursor: col-resize;
  opacity: 1;
  background-color: rgb(211, 36, 164);
}

拖拽右侧边栏

往左拖拽

如上图,红色方框圈住的部分是 container 的区域,即鼠标移动范围和侧边栏宽度变化的计算区域。

右侧边栏边缘处在整个 container 的 x 坐标是整个 container 的宽度减去右侧边栏的宽度,命名为 startWidth。假如,container 的宽度是 1355 px,右侧边栏的宽度是 100 px,那么 startWidth = 1355px - 100px = 1255px。

鼠标拖拽右侧边栏的左边缘处往左移动,得到一个鼠标监听事件,获取其数值:event.pageX。假如 event.pageX = 1200px,那么右侧边栏应该移动:

moveStep=startWidthevent.pageX=1255px1200px=55px

因此,右侧边栏由原来的 100px 增加 55px 得到的新宽度是 155px:

shiftWidth=moveStep+container.offsetLeft+right.clientWidth

const container = document.querySelector(".container");
const right = document.querySelector(".right");
const rightResizeBar = document.querySelector(".right .resize-bar");

function moveRightBar(event) {
  setTimeout(() => {
    let startWidth = container.clientWidth - right.clientWidth;
    let moveStep = startWidth - event.pageX;
    let shiftWidth = moveStep + container.offsetLeft + right.clientWidth;
    right.style.width = shiftWidth + "px";
    rightResizeBar.style.right = shiftWidth + "px";
  }, 200);
}

pageX、clientX 都是一样的数值,用哪个都可以。计算过程中有一个 container.offsetLeft,这是 container 距离浏览器窗口 x 为 0 处的左偏移量。因为 container 的宽度有可能不和浏览器窗口百分之百贴合,如果高和宽都小于浏览器窗口,且设置了垂直、水平居中,就存在左偏移量,即 offsetLeft。为了使侧边栏移动准确性,需要在 shiftWdith 计算的过程中加上container.offsetLeft

往右拖拽

startWidth 还是 1255px。鼠标拖拽右侧边栏的左边缘处往右移动,得到一个鼠标监听事件,获取其数值:event.pageX。假如 event.pageX = 1380px,那么右侧边栏应该移动:

moveStep=startWidthevent.pageX=1255px1280px=25px

因此,右侧边栏由原来的 100px 增加 -25px 得到的新宽度是 75px。

添加监听器

只有当用户鼠标按下拖拽的控制器(rightResizeBar)时,才开启鼠标在 container 中移动的事件,事件函数为 moveRightBar。moveRightBar 计算右侧边栏的移动距离。

当用户在 container 范围内或在 rightResizeBar 元素内鼠标放下时,就移除 container 的事件:

// 1. 鼠标按下 rightResizeBar 元素,开启 container 的事件监听
rightResizeBar.addEventListener("mousedown", () => {
  container.addEventListener("mousemove", moveRightBar);
});

// 2. 当鼠标从 rightResizeBar 放下时,取消监听
rightResizeBar.addEventListener("mouseup", () => {
  container.removeEventListener("mousemove", moveRightBar);
});

// 3. 当鼠标从 container 范围内放下时,取消监听
container.addEventListener("mouseup", () => {
  container.removeEventListener("mousemove", moveRightBar);
});

拖拽左侧边栏

左侧边栏的拖拽代码就非常简单了。鼠标不管从哪个方向移动,都是以浏览器左上角的原点为起点计算的鼠标 x、y 坐标值。而左侧边栏的左拖拽和右拖拽正好处于浏览器的左边部分,鼠标往左或往右拖拽多少 px,侧边栏的宽度就是event.pageX - container.offsetLeft

function moveLeftBar(event) {
  setTimeout(() => {
    let shiftWidth = event.pageX - container.offsetLeft;
    left.style.width = shiftWidth + "px";
    leftResizeBar.style.left = shiftWidth + "px";
  }, 200);
}

添加监听器

leftResizeBar.addEventListener("mousedown", () => {
  container.addEventListener("mousemove", moveLeftBar);
});

leftResizeBar.addEventListener("mouseup", () => {
  container.removeEventListener("mousemove", moveLeftBar);
});

container.addEventListener("mouseup", () => {
  container.removeEventListener("mousemove", moveLeftBar);
});

源码仓库

  • GitHub 源码地址
  • 在线预览地址