Горизонтальная сортировка

Shopify Draggable предоставляет мощный и гибкий инструмент для реализации интерактивного перетаскивания элементов на веб-странице. Одной из ключевых возможностей является горизонтальная сортировка, когда элементы можно переставлять по горизонтали, а библиотека автоматически обрабатывает логику перемещения, анимации и событий.


Инициализация Draggable для горизонтального списка

Для работы с горизонтальной сортировкой требуется создать контейнер с элементами, которые будут перетаскиваться. Пример структуры HTML:

<div id="sortable-container" class="draggable-container">
  <div class="draggable-item">Элемент 1</div>
  <div class="draggable-item">Элемент 2</div>
  <div class="draggable-item">Элемент 3</div>
  <div class="draggable-item">Элемент 4</div>
</div>

CSS для горизонтального расположения:

.draggable-container {
  display: flex;
  flex-direction: row;
  gap: 10px;
}

.draggable-item {
  padding: 15px 25px;
  background-color: #f2f2f2;
  border: 1px solid #ccc;
  cursor: grab;
  user-select: none;
}

JavaScript-инициализация Draggable с поддержкой горизонтальной сортировки:

import { Draggable } from '@shopify/draggable';

const container = document.getElementById('sortable-container');

const draggable = new Draggable(container, {
  draggable: '.draggable-item',
  mirror: {
    constrainDimensions: true
  },
  plugins: [Draggable.Plugins.Sortable]
});

Ключевой момент: flex-direction: row в CSS и использование плагина Sortable обеспечивают горизонтальное перетаскивание.


Настройка зеркального объекта (Mirror)

Зеркальный объект — это элемент, который создаётся при начале перетаскивания и визуально повторяет исходный элемент. Для горизонтальной сортировки важно контролировать его размеры и положение:

draggable.on('mirror:created', (event) => {
  const mirror = event.data.mirror;
  mirror.style.width = `${event.data.source.offsetWidth}px`;
  mirror.style.height = `${event.data.source.offsetHeight}px`;
});

Использование constrainDimensions: true гарантирует, что зеркальный элемент не изменяет размеры во время перетаскивания.


Обработка событий сортировки

Draggable предоставляет множество событий, которые можно использовать для управления логикой горизонтальной сортировки:

  • sortable:sort — срабатывает при перемещении элемента внутри контейнера.
  • sortable:sorted — срабатывает после завершения сортировки.
  • sortable:start и sortable:stop — начало и окончание перетаскивания.

Пример использования событий:

draggable.on('sortable:start', (event) => {
  console.log('Начало перемещения:', event.data.source.textContent);
});

draggable.on('sortable:sort', (event) => {
  console.log('Элемент перемещается:', event.data.source.textContent);
});

draggable.on('sortable:sorted', (event) => {
  console.log('Элемент перемещён:', event.data.source.textContent);
});

Эти события позволяют динамически отслеживать порядок элементов, обновлять состояние интерфейса и выполнять дополнительные действия, например, сохранять порядок на сервере.


Ограничение направления перетаскивания

Для горизонтальной сортировки часто необходимо запретить вертикальное перемещение элементов. Это достигается настройкой CSS контейнера и плавающих элементов, а также ограничением движения через Draggable:

draggable.on('drag:move', (event) => {
  event.data.mirror.style.transform = `translateX(${event.data.translate.x}px)`;
});

Плагин Sortable уже учитывает направление контейнера, но явное управление трансформацией даёт полный контроль над анимацией и предотвращает смещение по оси Y.


Использование нескольких контейнеров

Draggable поддерживает сортировку между несколькими горизонтальными контейнерами. Пример:

<div class="draggable-container" id="container-1">
  <div class="draggable-item">A1</div>
  <div class="draggable-item">A2</div>
</div>

<div class="draggable-container" id="container-2">
  <div class="draggable-item">B1</div>
  <div class="draggable-item">B2</div>
</div>

Jav * aScript:

const containers = document.querySelectorAll('.draggable-container');

const draggableMulti = new Draggable(containers, {
  draggable: '.draggable-item',
  plugins: [Draggable.Plugins.Sortable]
});

При использовании нескольких контейнеров важно следить за правильной установкой mirror и события sortable:sorted, чтобы корректно обновлять порядок элементов в каждом контейнере.


Оптимизация производительности

Для длинных списков рекомендуется:

  • Использовать requestAnimationFrame для обновления стилей зеркала.
  • Минимизировать количество операций DOM в событиях sortable:sort.
  • Ограничивать использование сложных CSS-анимаций, чтобы перетаскивание оставалось плавным.

Пример оптимизации зеркала:

draggable.on('drag:move', (event) => {
  requestAnimationFrame(() => {
    event.data.mirror.style.transform = `translateX(${event.data.translate.x}px)`;
  });
});

Адаптивность и мобильные устройства

Draggable поддерживает сенсорные устройства, однако для горизонтальной сортировки необходимо учитывать:

  • Минимальные размеры элементов для удобного тапа.
  • Использование touch-action: pan-x на контейнере, чтобы предотвратить конфликт с горизонтальной прокруткой страницы.
  • Проверка поведения на разных устройствах, так как события касания могут вести себя иначе, чем мышь.
.draggable-container {
  touch-action: pan-x;
}

Заключение технической части

Горизонтальная сортировка в Shopify Draggable сочетает простоту конфигурации и гибкость управления событиями. Правильная настройка CSS, зеркальных объектов и событий позволяет создавать динамичные интерфейсы с плавной анимацией и поддержкой мобильных устройств. Это обеспечивает удобный пользовательский опыт при работе с интерактивными горизонтальными списками.