使用滑块更改两个块的宽度比例

Mic*_*ael 5 javascript css flexbox vue.js

我正在尝试设计一个组件,您可以在其中通过左右移动滑块来更改两个块的宽度比例: 在此处输入图片说明

代码和演示:

.outer {
  display: flex;
  flex-direction: row;
}

.block {
  height: 200px;
  width: -webkit-calc(50% - 5px);
  width: -moz-calc(50% - 5px);
  width: calc(50% - 5px);
}

.block-1 {
  background-color: red;
}

.block-2 {
  background-color: green;
}

.slider {
  line-height: 100%;
  width: 10px;
  background-color: #dee2e6;
  border: none;
  cursor: e-resize;
}
Run Code Online (Sandbox Code Playgroud)
<div id="app">
  <div class="outer">
    <div class="block block-1">
      Block 1
    </div>
    <div class="slider">
      S<br>l<br>i<br>d<br>e<br>r
    </div>
    <div class="block block-2">
      Block 2
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我曾尝试draggable-vue-directive根据滑块位置使用和更改块的宽度。

然而,它并没有很好地工作,因为draggable-vue-directive将滑块设置为position:fixed反过来弄乱了块对齐。

如何在.slider不设置的情况下使块水平拖动position:fixed

如何正确调整大小Block1以及Block2滑块何时移动?

注意:我没有使用 jQuery

kuk*_*kuz 9

你可以调整你的Flexbox的沿resize-的缺点是,滑盖它不是非常可定制:

  • 添加resize: horizontal到弹性项目之一
  • 添加flex: 1到另一个 flex 项目(这样这个flex 项目将在调整大小时自动调整以响应另一个 flex 项目的宽度变化)

请参阅下面的演示:

.outer {
  display: flex;
  flex-direction: row;
}

.block {
  height: 100px;
  width: 50%; /* 50% would suffice*/
}

.block-1 {
  background-color: red;
  resize: horizontal; /* resize horizontal */
  overflow: hidden; /* resize works for overflow other than visible */
}

.block-2 {
  background-color: green;
  flex: 1; /* adjust automatically */
}
Run Code Online (Sandbox Code Playgroud)
<div id="app">
  <div class="outer">
    <div class="block block-1">
      Block 1
    </div>
    <div class="block block-2">
      Block 2
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)


所以我们将使用vanilla JS而不是上面的调整大小解决方案:

  • 使用mousedown该侦听器注册一个mousemove侦听器更新block-1宽度(和复位mouseup事件)
  • 也考虑min-width: 0覆盖 min-width: auto的的block-2元素

请参阅下面的演示:

let block = document.querySelector(".block-1"),
  slider = document.querySelector(".slider");

slider.onmousedown = function dragMouseDown(e) {
  let dragX = e.clientX;
  document.onmousemove = function onMouseMove(e) {
    block.style.width = block.offsetWidth + e.clientX - dragX + "px";
    dragX = e.clientX;
  }
  // remove mouse-move listener on mouse-up
  document.onmouseup = () => document.onmousemove = document.onmouseup = null;
}
Run Code Online (Sandbox Code Playgroud)
.outer {
  display: flex;
  flex-direction: row;
}

.block {
  height: 100px;
  width: 50%; /* 50% would suffice*/
}

.block-1 {
  background-color: red;
}

.block-2 {
  background-color: green;
  flex: 1; /* adjust automatically */
  min-width: 0; /* allow flexing beyond auto width */
  overflow: hidden; /* hide overflow on small width */
}

.slider {
  line-height: 100%;
  width: 10px;
  background-color: #dee2e6;
  border: none;
  cursor: col-resize;
  user-select: none; /* disable selection */
  text-align: center;
}
Run Code Online (Sandbox Code Playgroud)
<div id="app">
  <div class="outer">
    <div class="block block-1">
      Block 1
    </div>
    <div class="slider">
      S<br>l<br>i<br>d<br>e<br>r
    </div>
    <div class="block block-2">
      Block 2
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)


解决方案

您可以轻松地将上述内容调整到 Vue 中,而无需为此使用任何自定义 Vue 插件 - 更改如下:

  • @mousedown监听slider触发滑块

  • 用于refs更新宽度block-1

请参阅下面的演示:

new Vue({
  el: '#app',
  data: {
    block1W: '50%'
  },
  methods: {
    drag: function(e) {
      let dragX = e.clientX;
      let block = this.$refs.block1;
      document.onmousemove = function onMouseMove(e) {
        block.style.width = block.offsetWidth + e.clientX - dragX + "px";
        dragX = e.clientX;
      }
      // remove mouse-move listener on mouse-up
      document.onmouseup = () => document.onmousemove = document.onmouseup = null;
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
.outer {
  display: flex;
  flex-direction: row;
}

.block {
  height: 100px;
  width: 50%; /* 50% would suffice*/
}

.block-1 {
  background-color: red;
}

.block-2 {
  background-color: green;
  flex: 1; /* adjust automatically */
  min-width: 0; /* allow flexing beyond auto width */
  overflow: hidden; /* hide overflow on small width */
}

.slider {
  line-height: 100%;
  width: 10px;
  background-color: #dee2e6;
  border: none;
  cursor: col-resize;
  user-select: none; /* disable selection */
  text-align: center;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div class="outer">
    <div class="block block-1" ref="block1" :style="{'width': block1W}">
      Block 1
    </div>
    <div class="slider" @mousedown="drag">
      S<br>l<br>i<br>d<br>e<br>r
    </div>
    <div class="block block-2">
      Block 2
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)