最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Change width proportions of two blocks with a slider - Stack Overflow

programmeradmin6浏览0评论

I'm trying to design a ponent in which you could change the width proportions of two blocks by moving a slider left and right:

codpen and demo:

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

I'm trying to design a ponent in which you could change the width proportions of two blocks by moving a slider left and right:

codpen and demo:

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

I have tried using draggable-vue-directive and change the width of blocks based on slider position.

However, it didn't work really well, since draggable-vue-directive set the slider to position:fixed which in turn messed up the block alignment.

How can I make the .slider block horizontally draggable without setting position:fixed?

How to correctly resize Block1 and Block2 when slider moves?

Note: I'm not using jQuery

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Apr 7, 2019 at 13:30 MichaelMichael 16.2k39 gold badges98 silver badges145 bronze badges 2
  • There are lots of ways to make a slider. What are you trying to acplish with it? Your current implementation will simply reflow the content in each area as they bee wider/narrower. Is that the goal? – Bryce Howitson Commented Apr 7, 2019 at 14:53
  • @BryceHowitson yeah, basically if you slide the slider div to the right, then Block 1 should be wider and Block 2 should be narrower – Michael Commented Apr 7, 2019 at 15:09
Add a ment  | 

1 Answer 1

Reset to default 10

You can adjust your flexbox along with resize - the downside is that the slider its not very customizeable:

  • add resize: horizontal to one of the flex items
  • add flex: 1 to the other flex item (so that this flex item will adjust automatically in response to the changing width of the other flex item as it is resized)

See demo below:

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


So we'll use vanilla JS instead of the resize solution above:

  • use a mousedown listener that registers a mousemove listener that updates the block-1 width (and reset the mouseup event)
  • also consider min-width: 0 to override min-width: auto of the block-2 element

See demo below:

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


Solution

You can adapt the above into Vue easily without using any custom Vue plugins for this - the changes are:

  • @mousedown listener on slider that triggers the slider

  • use of refs to update the width of block-1

See demo below:

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;
}
<script src="https://cdnjs.cloudflare./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>

发布评论

评论列表(0)

  1. 暂无评论