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>
相关推荐
hackeroink12 分钟前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者2 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-2 小时前
验证码机制
前端·后端
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖4 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235244 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240255 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar5 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人6 小时前
前端知识补充—CSS
前端·css