Skip to content

前端实现拖拽 div 修改宽度

效果显示

div1
div3

代码实现

html 代码

Details
html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Resizable Divs</title>
    <style>
      /* 设置 html 和 body 的宽高,移除默认的边距 */
      html,
      body {
        width: 100vw;
        height: 100vh;
        margin: 0;
      }
      #container {
        display: flex; /* 使用弹性盒模型 */
        height: 100vh;
      }
      #div1 {
        flex: 0 0 205px;
        min-width: 205px; /* div1 的最小宽度 */
        max-width: 355px; /* div1 的最大宽度 */
      }
      #div1,
      #div3 {
        background: lightgrey; /* 背景颜色 */
        border: solid 1px #000; /* 边框 */
        box-sizing: border-box; /* 盒子模型 */
      }
      #div3 {
        flex: 1;
      }
      #div2 {
        box-sizing: border-box;
        width: 5px; /* 分隔条的宽度 */
        flex: 0 0 5px; /* 设置弹性盒子的基础宽度,不伸缩 */
        background: red; /* 分隔条的背景颜色 */
        cursor: ew-resize; /* 鼠标悬停时的光标样式 */
      }
    </style>
  </head>
  <body>
    <div id="container">
      <div id="div1">div1</div>
      <div id="div2"></div>
      <div id="div3">div3</div>
    </div>

    <script>
      const container = document.getElementById("container");
      const div1 = document.getElementById("div1");
      const div2 = document.getElementById("div2");
      const div3 = document.getElementById("div3");
      let startX,
        startWidth1,
        startWidth3; /* 初始化变量用于存储拖拽开始时的状态 */

      div2.addEventListener("mousedown", function (e) {
        startX = e.clientX; /* 记录鼠标按下时的x坐标 */
        startWidth1 = div1.offsetWidth; /* 记录 div1 当前的宽度 */
        startWidth3 = div3.offsetWidth; /* 记录 div3 当前的宽度 */
        // 应用 ew-resize 光标样式到整个文档
        document.body.style.cursor =
          "ew-resize"; /* 将整个文档的光标样式设置为 ew-resize */
        container.style.userSelect = "none"; /* 禁止拖拽时选中文本 */

        document.addEventListener(
          "mousemove",
          resize,
          false
        ); /* 监听鼠标移动事件 */
        document.addEventListener(
          "mouseup",
          stopResize,
          false
        ); /* 监听鼠标抬起事件 */
      });

      function resize(e) {
        const diffX = e.clientX - startX;
        let newWidth1 = startWidth1 + diffX;
        let newWidth3 = startWidth3 - diffX;

        // 检查div1是否超出最小或最大宽度,并相应调整
        if (newWidth1 < 205) {
          newWidth1 = 205;
        } else if (newWidth1 > 355) {
          newWidth1 = 355;
        }

        // 因为div2是div1和div3之间的分隔条,所以我们需要更新div3的宽度
        // 以保持总体宽度不变。我们这里假设容器的总宽度是不变的。
        newWidth3 = container.offsetWidth - newWidth1 - div2.offsetWidth;

        // 设置新宽度
        div1.style.flex = `0 0 ${newWidth1}px`;
        div3.style.width = `${newWidth3}px`;
      }

      function stopResize() {
        // 移除 ew-resize 光标样式,恢复到默认状态
        document.body.style.cursor = ""; /* 移除文档的光标样式设置 */
        container.style.userSelect = ""; /* 恢复文本选择功能 */

        /* 移除鼠标事件监听器 */
        document.removeEventListener("mousemove", resize, false);
        document.removeEventListener("mouseup", stopResize, false);
      }
    </script>
  </body>
</html>

vue3 代码

Details
vue
<template>
  <div ref="container" id="container">
    <div ref="div1" id="div1">div1</div>
    <div ref="div2" id="div2" @mousedown="startResize"></div>
    <div ref="div3" id="div3">div3</div>
  </div>
</template>

<script setup>
import { ref } from "vue";

const container = ref(null);
const div1 = ref(null);
const div2 = ref(null);
const div3 = ref(null);
let startX, startWidth1, startWidth3;

const startResize = (e) => {
  startX = e.clientX;
  startWidth1 = div1.value.offsetWidth;
  startWidth3 = div3.value.offsetWidth;
  document.body.style.cursor = "ew-resize";
  container.value.style.userSelect = "none";

  document.addEventListener("mousemove", resize, false);
  document.addEventListener("mouseup", stopResize, false);
};

const resize = (e) => {
  const diffX = e.clientX - startX;
  let newWidth1 = startWidth1 + diffX;
  let newWidth3 = startWidth3 - diffX;

  // 限制div1的宽度在最小和最大值之间
  newWidth1 = Math.max(205, Math.min(newWidth1, 355));
  // 调整div3的宽度,确保容器的总宽度不变
  newWidth3 = container.value.offsetWidth - newWidth1 - div2.value.offsetWidth;

  // 设置新的宽度
  div1.value.style.flex = `0 0 ${newWidth1}px`;
  //   div3.value.style.width = `${newWidth3}px`;
};

const stopResize = () => {
  document.body.style.cursor = "";
  container.value.style.userSelect = "";
  document.removeEventListener("mousemove", resize, false);
  document.removeEventListener("mouseup", stopResize, false);
};
</script>

<style>
#container {
  display: flex;
  height: 400px; /* 设置容器高度为 400px */
  user-select: none;
}

#div1,
#div3 {
  background: lightgrey;
  border: solid 1px #000;
  box-sizing: border-box;
}

#div1 {
  min-width: 205px; /* div1 的最小宽度 */
  max-width: 355px; /* div1 的最大宽度 */
  flex: 0 0 205px;
}

#div3 {
  flex: 1;
}

#div2 {
  box-sizing: border-box;
  width: 5px;
  flex: 0 0 5px;
  background: red;
  cursor: ew-resize;
}
</style>