Создание двойного ползунка (double range slider) с помощью NoUiSlider — это отличное решение, когда нужно дать пользователям возможность выбирать диапазон значений, например, для фильтрации цен или других числовых параметров. В этой статье мы рассмотрим, как создать двойной ползунок (или double range slider) с помощью плагина NoUiSlider.
Когда дело касается пользовательского интерфейса, удобство и точность ввода данных становятся важными критериями. Один из самых простых и интуитивно понятных инструментов для этого — ползунок, особенно когда требуется указать не одно, а два значения: минимальное и максимальное. Например, фильтрация товаров по цене на сайте магазина.
В JavaScript существует множество решений для создания ползунков, но одним из наиболее популярных и гибких является библиотека NoUiSlider. Она проста в установке и имеет множество настроек. Сейчас мы покажем, как сделать двойной ползунок и связать его с текстовыми полями для ввода значений.
Установка NoUiSlider
Для начала вам нужно добавить библиотеку в ваш проект. Как и любой современный плагин, NoUiSlider можно подключить через CDN или загрузить локально.
В нашем примере я уже подключил необходимые стили и скрипты:
<link rel="stylesheet" href="css/nouislider.min.css" />
<script src="js/nouislider.min.js"></script>
Создание структуры HTML
Мы создаем простой макет страницы с двумя текстовыми полями, где пользователь может вводить минимальное и максимальное значения, и сам ползунок, с помощью которого можно эти значения регулировать. Вот как это выглядит:
<div class="container">
<div class="wrapper">
<div class="silder">
<div class="flex flex--column">
<h1 class="slider__title">Двойной ползунок (плагин NoUiSlider)</h1>
<p class="slider__subtitle">
Используйте ползунок или вводите диапазон значений в поле
</p>
</div>
<div class="flex flex--h-center flex--v-center">
<input type="number" name="min_num" id="min_num" class="slider__field" placeholder="от" />
<span class="slider__separator">—</span>
<input type="number" name="max_num" id="max_num" class="slider__field" placeholder="до" />
</div>
<div class="slider__self" id="slider"></div>
</div>
</div>
</div>
Что здесь происходит?
- Заголовок и описание: просто добавляем немного контекста для пользователя.
- Два текстовых поля: сюда пользователь может ввести минимальное и максимальное значения вручную.
- Сам ползунок: элемент, который будет визуально отображать диапазон значений и позволять их менять.
Стилизация
Для того чтобы ползунок выглядел красиво, мы добавили немного CSS. В примере выше вы увидите базовые стили для полей ввода, самого ползунка и его маркеров. Мы также задали яркий цвет для выделения выбранного диапазона:
/* Основные стили для фона страницы */
body {
background-color: #4285f4; /* Синий фон */
}
/* Стили для заголовка ползунка */
.slider__title {
font-size: 26px; /* Размер текста */
margin-bottom: 10px; /* Отступ снизу */
text-align: center; /* Выравнивание текста по центру */
}
/* Стили для подзаголовка */
.slider__subtitle {
margin-bottom: 30px; /* Отступ снизу */
text-align: center; /* Выравнивание текста по центру */
}
/* Стили для текстовых полей ввода значений */
.slider__field {
width: 100px; /* Ширина поля */
padding: 10px; /* Внутренние отступы */
border-radius: 5px; /* Скругленные углы */
background-color: #fff; /* Белый фон */
border: 1px solid #bbb; /* Серые границы */
font-size: 20px; /* Размер текста */
text-align: center; /* Выравнивание текста по центру */
}
/* Изменение стиля поля при фокусе */
.slider__field:focus {
border: 1px solid #4285f4; /* Синяя граница при фокусе */
}
/* Стили для разделителя между полями */
.slider__separator {
font-size: 20px; /* Размер текста */
font-weight: 300; /* Тонкий шрифт */
line-height: 1; /* Высота строки */
margin-left: 10px; /* Отступ слева */
margin-right: 10px; /* Отступ справа */
}
/* Стили для самого ползунка */
.slider__self {
width: 500px; /* Ширина ползунка */
cursor: pointer; /* Указатель меняется на руку при наведении */
height: 7px; /* Высота ползунка */
border: none; /* Убираем границы */
background-color: #dedede; /* Серый фон для трека */
margin-top: 30px; /* Отступ сверху */
}
/* Стили для выделенной части ползунка между значениями */
.slider__self .noUi-connect {
background-color: rgba(66, 133, 244, 0.5); /* Полупрозрачный синий цвет для соединения */
}
/* Стили для маркеров (ползунков) */
.slider__self .noUi-handle {
cursor: pointer; /* Указатель меняется на руку при наведении */
height: 30px; /* Высота маркера */
width: 30px; /* Ширина маркера */
top: -12px; /* Смещение сверху для выравнивания */
right: -9px; /* Смещение справа для точной позиции */
border-radius: 50%; /* Скругляем маркеры до формы круга */
border: none; /* Убираем границы */
box-shadow: none; /* Убираем тени */
background-color: rgba(66, 133, 244, 1); /* Ярко-синий цвет маркера */
}
/* Убираем дефолтные стили маркеров */
.slider__self .noUi-handle::after {
display: none; /* Отключаем псевдоэлемент ::after */
}
.slider__self .noUi-handle::before {
display: none; /* Отключаем псевдоэлемент ::before */
}
/* Основные стили контейнера */
.container {
width: 100%; /* Ширина 100% от экрана */
max-width: 1200px; /* Максимальная ширина */
padding: 0 20px; /* Внутренние отступы по горизонтали */
height: 100%; /* Высота 100% от родительского контейнера */
margin: 0 auto; /* Центрируем блок */
display: flex; /* Используем Flexbox */
flex-direction: column; /* Выстраиваем элементы по колонке */
align-items: center; /* Центрируем по горизонтали */
justify-content: center; /* Центрируем по вертикали */
}
/* Стили обертки контента */
.wrapper {
background-color: #fff; /* Белый фон */
padding: 50px; /* Внутренние отступы */
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.06); /* Легкая тень для объема */
border-radius: 20px; /* Скругленные углы */
}
/* Общие стили для Flexbox */
.flex {
display: flex; /* Включаем Flexbox */
}
/* Вертикальная ориентация элементов */
.flex--column {
flex-direction: column; /* Элементы выстраиваются вертикально */
}
/* Горизонтальное центрирование */
.flex--h-center {
justify-content: center; /* Центрируем элементы по горизонтали */
}
/* Вертикальное центрирование */
.flex--v-center {
align-items: center; /* Центрируем элементы по вертикали */
}
Логика JavaScript
Теперь приступим к настройке самого ползунка. Мы будем использовать noUiSlider.create(), чтобы задать начальные значения, минимумы и максимумы, а также связывать ползунок с нашими текстовыми полями.
const slider = document.querySelector("#slider");
const formatForSlider = {
from: function (formattedValue) {
return Number(formattedValue); // Преобразуем форматированное значение в число
},
to: function (numericValue) {
return Math.round(numericValue); // Округляем число до ближайшего целого
},
};
noUiSlider.create(slider, {
start: [200, 800], // Начальные значения ползунка
connect: true, // Соединяет два значения цветом
range: {
min: 0, // Минимальное значение
max: 1000, // Максимальное значение
},
format: formatForSlider, // Форматируем значения при вводе/выводе
});
Разбор кода
- slider: это элемент, который будет превращен в ползунок.
- formatForSlider: это объект, который управляет преобразованием значений. Он нужен, чтобы округлять значения, так как плавающие числа могут создавать неудобства пользователям.
- noUiSlider.create(): создает сам ползунок. Мы указываем стартовые значения [200, 800], задаем минимальный и максимальный диапазон значений от 0 до 1000 и добавляем соединение между двумя значениями ползунка для наглядности.
Связывание с текстовыми полями
Теперь добавим логику, которая будет обновлять значения в текстовых полях при изменении ползунка и наоборот.
const formatValues = [
document.getElementById("min_num"), // Поле для минимального значения
document.getElementById("max_num"), // Поле для максимального значения
];
slider.noUiSlider.on("update", function (values, handle) {
formatValues[handle].value = values[handle]; // Обновляем поля при движении ползунка
});
Что происходит?
- При изменении положения ползунка событие update срабатывает каждый раз, когда одно из значений меняется.
- values: массив значений ползунка.
- handle: индекс ручки (0 — левая, 1 — правая), это помогает определить, какое поле обновить: минимальное или максимальное.