Создание слайдера диапазона значений для фильтра без использования Jquery

от автора

Очень часто на сайтах интернет-магазинов, и не только, можно фильтры со слайдером выбора диапазона значений. В одном из проектов мне тоже понадобилось сделать такой слайдер.

Первое, что приходит в голову — найти уже готовый и вставить себе на сайт. Тут то я и столкнулся с проблемой. Найденный мною плагин JqueryUI.slider отказался работать на некоторых мобильных устройствах. Проблему я выявить не смог (да не особо и хотел ковыряться в чужом коде) и решил сделать свой "велосипед".

"Велосипед" я решил делать на чистом JavaScript, чтобы не связываться с библиотеками. Как говорит один мой знакомый: "чем меньше "левых" подключений, тем стабильней все работает".

Поэтому, первым делом сверстал такой вот простенький макет

<div class="filter">         <div>             <span>Фильтр 1</span>             <div><number>10</number><number>50</number></div>             <div class="slider">                 <div class="block-min" onMouseDown="moveRange(this)" onTouchStart="moveRange(this)"></div>                 <div class="color-range"></div>                 <div class="block-max" onMouseDown="moveRange(this)" onTouchStart="moveRange(this)"></div>             </div>         </div>         <div>             <span>Фильтр 2</span>             <div><number>0</number><number>5</number></div>             <div class="slider">                 <div class="block-min" onMouseDown="moveRange(this)" onTouchStart="moveRange(this)"></div>                 <div class="color-range"></div>                 <div class="block-max" onMouseDown="moveRange(this)" onTouchStart="moveRange(this)"></div>             </div>         </div>     </div>

На экране он выглядит так

Сам слайдер с ползунками находится в блоке с классом "slider" в котором есть еще 2 блока: ползунок минимального значения и ползунок максимального значения диапазона.
В них описаны два события:

  1. onMouseDown — срабатывает, когда мы захватываем мышью ползунок;
  2. onTouchStart — срабатывает на мобильных устройствах, при касании пальца к нашему ползунку.

Над slider-ом размещается блок с двумя числами — это и есть наши максимальное и минимальное значения.

<div><number>0</number><number>5</number></div>

Теперь перейдем к самой функции, которая вызывается при клике.

function moveRange (elem) {         //Определяем размеры и координаты нашего ползунка     var coords = getCoords(elem);      /*Определяем зону окрашивания*/     var colorRange = elem.parentElement.children[1];     var f;//устанавливаем флаг для определения мин или макс элемента     var value; //значение фильтра      /*Определяем второй ползунок и родителя*/     var parent = {}         parent.element = elem.parentElement;         parent.coords = getCoords(parent.element);      var block2 = {}     if (elem.classList.contains('block-min')) {         block2.element = elem.parentElement.children[2];         block2.coords = getCoords(block2.element);         f=0;     } else {         block2.element = elem.parentElement.children[0];         block2.coords = getCoords(block2.element);         f=1;     }      /*Делаем индикатор вывода значений над ползунком*/     var indicator = document.createElement('div');     if (elem.children.length){         elem.innerHTML = '';//обнуляем предыдущее значение     }     elem.append(indicator);      document.addEventListener('mousemove', onMouseMove);//определяем функцию-обработчик на событие движения мышью     document.addEventListener('mouseup', onMouseUp);//определяем функцию-обработчик на событие отпускания кнопки мыши     document.addEventListener('touchmove', onMouseMove);//здесь все тоже самое, только на касание пальцем     document.addEventListener('touchend', onMouseUp);      /*выключаем браузерное событие DaD*/     elem.ondragstart = function(){         return false;     }

Функция getCoords позволяет нам получить координаты и размеры наших элементов.
Выглядит она следующим образом.

function getCoords(elem) {     /*Получаем координаты относительно окна браузера*/     let coords = elem.getBoundingClientRect();     /*Высчитываем значения координат относительно документа, вычисляя прокрутку документа*/     return {//возвращает объект, который содержит:         top : coords.top + window.pageYOffset, //верхнюю координату элемента относительно страницы         left : coords.left + window.pageXOffset, //крайнюю левую координату элемента относительно страницы         leftX: coords.left, //левую координату относительно страницы         rigth : coords.left + window.pageXOffset + coords.width, //крайнюю правую координату         bottom : coords.top + window.pageYOffset + coords.height, //нижнюю координату         width : coords.width //ширину элемента     } }

Теперь опишем функции-обработчики.
Первая функция — onMouseMove, которая вызывается при движении мышью. Она будет отрабатывать только при горизонтальном движении.

function onMouseMove(e) {          /*Определяем смещение влево*/         e.preventDefault();//предотвратить запуск выделения элементов          /*Определяем положение мыши в зависимости от устройства*/         /*На мобильных устройствах может фиксироваться несколько точек касания, поэтому используется массив targetTouches*/         /*Мы будем брать только первое зафиксированое касание по экрану targetTouches[0]*/         if (e.touches === undefined) {             var pos = e.clientX;         } else {             var pos = e.targetTouches[0].clientX;         }          /*Устанавливаем границы движения ползунка*/         let newLeft = pos - parent.coords.leftX;         let rigthEdge = parent.coords.width - (coords.width+1);          if (newLeft<0) {             newLeft = 0;         } else if (newLeft > rigthEdge) {             newLeft = rigthEdge;         }         if (f == 0 && pos > block2.coords.left-block2.coords.width) {             newLeft = block2.coords.left - block2.coords.width - 5 - parent.coords.leftX;         }else if (f == 1 && pos < block2.coords.rigth + 5) {             newLeft = block2.coords.rigth + 5 - parent.coords.leftX;         }         /*устанавливаем отступ нашему элементу*/         elem.style.left = newLeft + 'px';          //     Определяем значение фильтра         let rangeMin = +document.querySelector('.filter number:first-child').innerHTML;         let rangeMax = +document.querySelector('.filter number:last-child').innerHTML;         if(f==0){           value =  (newLeft / (parent.coords.width / (rangeMax - rangeMin)) + rangeMin).toFixed(1);         } else {           value = (newLeft / (parent.coords.width / (rangeMax - rangeMin))+ 0.3 + rangeMin).toFixed(1);         }          /*Выводим значение над ползунком*/         indicator.style.position = 'absolute';         indicator.style.fontSize = "14px";         indicator.style.left = - coords.width/2 + "px";         indicator.style.top = parseFloat(window.getComputedStyle(elem).getPropertyValue('top')) - 10 +"px";          /*Для красоты слайдера уберем вывод значений в начальной и конечной точках*/         if (newLeft <= 0){             indicator.innerHTML= "";         } else if (newLeft >= rigthEdge) {             indicator.innerHTML= "";         } else {             indicator.innerHTML = value;         }          /*Делаем цветную плашечку диапазона выбора*/         if (f == 0) {             colorRange.style.left = newLeft + coords.width + "px";             colorRange.style.width = block2.coords.left - getCoords(elem).left - coords.width + "px";         }  else {             colorRange.style.left = block2.coords.left - parent.coords.leftX + "px";             colorRange.style.width = getCoords(elem).left - block2.coords.left + "px";         }     }

И, наконец, функция-обработчик события "отпускания кнопки" или потери точки касания на мобильных устройствах. Она удаляет все добавленные ранее события и оставляет ползунок на установленном значении.

function onMouseUp() {         document.removeEventListener('mouseup', onMouseUp);         document.removeEventListener('mousemove', onMouseMove);         document.removeEventListener('touchend', onMouseUp);         document.removeEventListener('touchmove', onMouseMove);     }

И, конечно же, CSS-стили для нашего слайдера

.filter {     padding: 30px;     width: 500px; } .filter>div {     padding-top: 20px;     display: -webkit-flex;     display: -moz-flex;     display: -ms-flex;     display: -o-flex;     display: flex;     -webkit-flex-direction: column;     -moz-flex-direction: column;     -ms-flex-direction: column;     -o-flex-direction: column;     flex-direction: column; } .filter>div>div {     display: -webkit-flex;     display: -moz-flex;     display: -ms-flex;     display: -o-flex;     display: flex;     justify-content: space-between; } .filter .slider {     margin-top: 10px;     position: relative;     height: 6px;     background: #fff;     border: 1px solid #000; } .filter .color-range {     position: absolute;     background: #a4a4a4;     width: 97%;     border: none;     height: 6px;     left: 15px; } .filter .block-min, .block-max {   width: 15px;   height: 25px;   position: absolute;   left: 0;   top: -11.5px;   background: #fff;   border: 1px solid #000;   border-radius: 4px;   z-index: 1; } .filter .block-max{     left: 97%; }

Посмотреть рабочую версию данного слайдера можно здесь.

Все файлы можно скачать с GitHub.

Приятного пользования и легкой работы!


ссылка на оригинал статьи https://habr.com/ru/post/466623/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *