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

时间:2019-04-07 13:30:06

标签: javascript css css3 vue.js flexbox

我正在尝试设计一个组件,在其中您可以通过左右移动滑块来更改两个块的宽度比例: enter image description here

codpen和演示:

.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;
}
<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>

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

但是,由于draggable-vue-directive将滑块设置为position:fixed,因此效果并不理想。

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

如何在滑块移动时正确调整Block1Block2的大小?

注意:我没有使用jQuery

1 个答案:

答案 0 :(得分:3)

您可以调整您的 flexbox 以及resize- 缺点 滑块它不是非常可定制的:

  • resize: horizontal添加到其中一个弹性项目
  • flex: 1添加到另一个弹性项目中(以便弹性项目会随着调整大小的另一个弹性项目的宽度变化而自动调整)

请参见下面的演示

.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 */
}
<div id="app">
  <div class="outer">
    <div class="block block-1">
      Block 1
    </div>
    <div class="block block-2">
      Block 2
    </div>
  </div>
</div>


因此,我们将使用香草JS 代替上面的 resize 解决方案:

  • 使用注册了{em>的mousedown监听器更新mousemove宽度的block-1监听器(并重置 {{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;
}
.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;
}


解决方案

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

    <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>上的
  • @mousedown监听器,触发滑块

  • 使用refs更新slider

  • 的宽度

请参见下面的演示

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;
    }
  }
});
.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;
}