Я пытаюсь разработать компонент, в котором вы могли бы изменить пропорции ширины двух блоков, перемещая ползунок влево и вправо:
кутник и демо:
.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
?
Как правильно изменить размер Block1
и Block2
при перемещении ползунка?
Примечание: я не использую jQuery
@BryceHowitson да, в основном, если вы переместите ползунок div
вправо, то Block 1
должен быть шире, а Block 2
должен быть уже
Вы можете настроить флексбокс вместе с 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 вместо решения изменить размер выше:
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 — изменения таковы:
См. демо ниже:
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>
Действительно отличный ответ. Также очень приятно, что решение сначала основано на «ванильном» JS, а затем «мигрировало» в решение, ориентированное на Vue. Лично я бы просто использовал addEventListener
вместо использования свойств "on..." в JS, но здесь это не важно для общей функциональности. Хорошая работа. Спасибо большое.
Существует множество способов сделать слайдер. Чего вы пытаетесь добиться с его помощью? Ваша текущая реализация будет просто перекомпоновывать контент в каждой области по мере того, как они становятся шире/уже. Это цель?