JavaScript和vue实现左右两栏,中间拖动按钮可以拖动左右两边的宽度

JavaScript实现:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <title>拖动效果</title>
  <style>
body, html {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: Arial, sans-serif;
}

.container {
  display: flex;
  height: 100vh;
  position: relative;
}

.left-column, .right-column {
  flex-grow: 1;
  padding: 20px;
  box-sizing: border-box;
}

.left-column {
  background-color: #f0f0f0;
}

.right-column {
  background-color: #e0e0e0;
}

.divider {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 10px;
  cursor: ew-resize;
  background-color: #ccc;
  z-index: 1;
  left: calc(33.333% - 5px); /* 初始位置设为 33.333% 宽度减去一半的分割线宽度 */
}

.handle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 20px;
  height: 20px;
  background-color: #666;
  border-radius: 50%;
  cursor: ew-resize;
}


  </style>
</head>
<body>
  <div class="container">
    <div class="left-column">
      <h2>Left Column</h2>
      <p>This is the left column.</p>
    </div>
    <div class="divider" id="divider">
      <span class="handle"></span>
    </div>
    <div class="right-column">
      <h2>Right Column</h2>
      <p>This is the right column.</p>
    </div>
  </div>

  <script>
// scripts.js

document.addEventListener('DOMContentLoaded', function() {
  const divider = document.getElementById('divider');
  let isDragging = false;
  let initialX = 0;
  let initialWidth = 0;
  const container = document.querySelector('.container');

  // 设置初始位置
  const initialLeftPosition = container.offsetWidth * (1/3) - divider.offsetWidth / 2;
  divider.style.left = `${initialLeftPosition}px`;
  document.querySelector('.left-column').style.width = `${initialLeftPosition + divider.offsetWidth}px`;
  document.querySelector('.right-column').style.width = `${container.offsetWidth - (initialLeftPosition + divider.offsetWidth)}px`;

  // 监听鼠标按下事件
  divider.addEventListener('mousedown', function(e) {
    isDragging = true;
    initialX = e.clientX;
    initialWidth = divider.offsetLeft;
    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', stopDragging);
  });

  // 监听鼠标移动事件
  function drag(e) {
    if (!isDragging) return;
    const delta = e.clientX - initialX;
    const newLeftPosition = initialWidth + delta;
    const maxWidth = container.offsetWidth - divider.offsetWidth;
    const minWidth = 150; // 设定最小宽度
    const maxWidthLeft = maxWidth / 2; // 左侧最大宽度为一半的容器宽度
    const maxWidthRight = maxWidth / 2; // 右侧最大宽度为一半的容器宽度

    if (newLeftPosition >= minWidth && newLeftPosition <= maxWidthLeft) {
      divider.style.left = `${newLeftPosition}px`;
      document.querySelector('.left-column').style.width = `${newLeftPosition + divider.offsetWidth}px`;
      document.querySelector('.right-column').style.width = `${maxWidth - newLeftPosition}px`;
    }
  }

  // 监听鼠标抬起事件
  function stopDragging() {
    isDragging = false;
    document.removeEventListener('mousemove', drag);
    document.removeEventListener('mouseup', stopDragging);
  }
});
  </script>
</body>
</html>

Vue2实现:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue 2拖动效果</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <style>
/* styles.css */

body, html {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: Arial, sans-serif;
}

.container {
  display: flex;
  height: 100vh;
  position: relative;
}

.left-column, .right-column {
  flex-grow: 1;
  padding: 20px;
  box-sizing: border-box;
}

.left-column {
  background-color: #f0f0f0;
}

.right-column {
  background-color: #e0e0e0;
}

.divider {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 10px;
  cursor: ew-resize;
  background-color: #ccc;
  z-index: 1;
  left: 0; /* 调整初始位置为 0 */
}

.handle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 20px;
  height: 20px;
  background-color: #666;
  border-radius: 50%;
  cursor: ew-resize;
}
  </style>
</head>
<body>
  <div id="app">
    <div class="container">
      <div class="left-column" :style="{width: leftColumnWidth + 'px'}">
        <h2>Left Column</h2>
        <p>This is the left column.</p>
      </div>
      <div class="divider" ref="divider" @mousedown="startDragging">
        <span class="handle"></span>
      </div>
      <div class="right-column" :style="{width: rightColumnWidth + 'px'}">
        <h2>Right Column</h2>
        <p>This is the right column.</p>
      </div>
    </div>
  </div>
<script>

new Vue({
  el: '#app',
  data: {
    leftColumnWidth: 300,
    rightColumnWidth: 0,
    isDragging: false,
    initialX: 0,
    initialWidth: 0,
    containerWidth: 0,
    minWidth: 150, // 最小宽度
    maxWidth: 0, // 最大宽度
  },
  mounted() {
    this.containerWidth = document.querySelector('.container').clientWidth;
    this.maxWidth = Math.floor(this.containerWidth / 2) - 10; // 减去分割线的宽度
    this.rightColumnWidth = this.containerWidth - this.leftColumnWidth - 10;
    document.addEventListener('mousemove', this.drag);
    document.addEventListener('mouseup', this.stopDragging);

    // 设置初始位置
    const divider = this.$refs.divider;
    divider.style.left = `${this.leftColumnWidth}px`;
  },
  methods: {
    startDragging(e) {
      this.isDragging = true;
      this.initialX = e.clientX;
      this.initialWidth = this.leftColumnWidth;
    },
    drag(e) {
      if (!this.isDragging) return;
      const delta = e.clientX - this.initialX;
      const newLeftWidth = this.initialWidth + delta;

      if (newLeftWidth >= this.minWidth && newLeftWidth <= this.maxWidth) {
        this.leftColumnWidth = newLeftWidth;
        this.rightColumnWidth = this.containerWidth - newLeftWidth - 10;

        // 更新 divider 的位置
        const divider = this.$refs.divider;
        divider.style.left = `${this.leftColumnWidth}px`;
      }
    },
    stopDragging() {
      this.isDragging = false;
    }
  }
});
</script>
</body>
</html>
相关推荐
笃行35014 分钟前
集中式与分布式,KingbaseES 的四种形态共用一套内核
前端
陈随易1 小时前
Vue 编译器换掉 source map,快了三四成
前端·后端·程序员
ZhengEnCi3 小时前
12 种高级 UI 交互效果及对应 AI 提示词:从按压回弹到底部抽屉的物理感教学
前端·css·交互设计
IT_陈寒5 小时前
Redis大key删除为什么会导致服务卡顿?我的线上事故复盘
前端·人工智能·后端
系统集成-鹰翔5 小时前
ERP图片改名后仍命中识别缓存:缓存键、十分钟到期与调用计数
javascript·经验分享·后端
用户2705077725246 小时前
MCP 最小 Server 实测:3 个 JSON-RPC 报错与修法
前端
用户499335025076 小时前
一人VIP账号多人共用:Web 代理里的会话共享怎么实现
前端
用户老李6 小时前
无线电自学教程 05:第一台收音机——从矿石机到 SDR
前端
IPIPD6 小时前
Node.js请求遇到503怎么重试?先解析Retry-After,再做有上限退避
前端
葡萄城技术团队6 小时前
dsh-spreadjs-editor 的集成链路:把 SpreadJS Designer 嵌进 Agent 工作台
前端