使用滑块更改两个块的宽度比例 [英] Change width proportions of two blocks with a slider
问题描述
我正在尝试设计一个组件,在其中您可以通过左右移动滑块来更改两个块的宽度比例:
I'm trying to design a component in which you could change the width proportions of two blocks by moving a slider left and right:
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
并根据以下内容更改块的宽度滑块位置.
I have tried using draggable-vue-directive
and change the width of blocks based on slider position.
但是,由于draggable-vue-directive
将滑块设置为position:fixed
,这反过来搞乱了块对齐方式,因此效果并不理想.
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.
如何在不设置position:fixed
的情况下使.slider
块水平拖动?
How can I make the .slider
block horizontally draggable without setting position:fixed
?
当滑块移动时如何正确调整Block1
和Block2
的大小?
How to correctly resize Block1
and Block2
when slider moves?
注意:我没有使用jQuery
推荐答案
You can adjust your flexbox along with resize
- the downside is that the slider its not very customizeable:
- 将
resize: horizontal
添加到一个弹性项目中 - 将
flex: 1
添加到另一个弹性项目中(以便此弹性项目将随着调整其大小而变化的另一个弹性项目的宽度而自动调整)
- 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)
请参见下面的演示
.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 解决方案:
So we'll use vanilla JS instead of the resize solution above:
- 使用注册的
mousedown
监听器更新block-1
宽度(并 resetmouseup
事件的)mousemove
监听器 - 还考虑将
min-width: 0
替换为元素的 min-width: auto
- use a
mousedown
listener that registers amousemove
listener that updates theblock-1
width (and reset themouseup
event) - also consider
min-width: 0
to overridemin-width: auto
of theblock-2
element
请参见下面的演示
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,而无需-更改为:
You can adapt the above into Vue easily without using any custom Vue plugins for this - the changes are:
-
@mousedown
侦听器,触发滑块
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>
这篇关于使用滑块更改两个块的宽度比例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!