Изменение пропорций ширины двух блоков с помощью ползунка

Я пытаюсь разработать компонент, в котором вы могли бы изменить пропорции ширины двух блоков, перемещая ползунок влево и вправо: Изменение пропорций ширины двух блоков с помощью ползунка

кутник и демо:

.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

Существует множество способов сделать слайдер. Чего вы пытаетесь добиться с его помощью? Ваша текущая реализация будет просто перекомпоновывать контент в каждой области по мере того, как они становятся шире/уже. Это цель?

Bryce Howitson 07.04.2019 16:53

@BryceHowitson да, в основном, если вы переместите ползунок div вправо, то Block 1 должен быть шире, а Block 2 должен быть уже

Michael 07.04.2019 17:09
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
2
1 215
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете настроить флексбокс вместе с 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 — изменения таковы:

  • @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>

Действительно отличный ответ. Также очень приятно, что решение сначала основано на «ванильном» JS, а затем «мигрировало» в решение, ориентированное на Vue. Лично я бы просто использовал addEventListener вместо использования свойств "on..." в JS, но здесь это не важно для общей функциональности. Хорошая работа. Спасибо большое.

Bart Hofland 17.07.2019 10:54

Другие вопросы по теме