使用滑块更改两个块的宽度比例
Posted
技术标签:
【中文标题】使用滑块更改两个块的宽度比例【英文标题】:Change width proportions of two blocks with a slider 【发布时间】:2019-08-28 18:46:36 【问题描述】:我正在尝试设计一个组件,您可以在其中通过左右移动滑块来更改两个块的宽度比例:
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
,这反过来又搞乱了块对齐。
如何在不设置position:fixed
的情况下使.slider
块水平拖动?
当滑块移动时如何正确调整Block1
和Block2
的大小?
注意:我没有使用jQuery
【问题讨论】:
制作滑块的方法有很多。你想用它来完成什么?您当前的实现将简单地重排每个区域中的内容,因为它们变得更宽/更窄。这是目标吗? @BryceHowitson 是的,基本上如果您将滑块div
向右滑动,那么 Block 1
应该更宽,Block 2
应该更窄
【参考方案1】:
你可以调整你的 flexbox 和 resize
- 缺点是 slider 它不是非常可定制:
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>
所以我们将使用 vanilla JS 代替上面的 resize 解决方案:
使用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;
.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>
解决方案
您可以轻松地将上述内容调整为 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;
);
.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.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>
【讨论】:
确实很好的答案。该解决方案首先基于“vanilla” JS,然后“迁移”到以 Vue 为目标的解决方案,这也很不错。就个人而言,我只会使用addEventListener
而不是在 JS 中使用“on...”属性,但这对于一般功能来说并不重要。干得好。非常感谢。以上是关于使用滑块更改两个块的宽度比例的主要内容,如果未能解决你的问题,请参考以下文章