Механика drag-and-drop не ограничивается перемещением элементов. Для пользователя важны визуальные сигналы, отражающие текущее состояние взаимодействия. Библиотека Shopify Draggable предоставляет встроенную систему классов и событий, позволяющих отображать различные стадии перетаскивания.
Ключевые состояния взаимодействия:
Каждое из этих состояний может быть визуализировано через CSS-классы или обработчики событий.
Библиотека автоматически добавляет служебные классы к элементам в процессе работы.
Основные классы:
| Класс | Назначение |
|---|---|
draggable--is-dragging |
элемент находится в процессе перетаскивания |
draggable--over |
элемент находится над допустимой областью |
draggable--placed |
элемент успешно размещён |
draggable--source |
исходный элемент, который был захвачен |
draggable--mirror |
визуальная копия перетаскиваемого элемента |
Использование этих классов позволяет управлять состояниями интерфейса исключительно средствами CSS.
Пример оформления:
.draggable--is-dragging {
opacity: 0.4;
}
.draggable--mirror {
background: #ffffff;
border: 2px dashed #444;
transform: scale(1.05);
}
.draggable--over {
background: #f2f6ff;
}
.draggable--placed {
animation: dropSuccess 0.25s ease;
}
@keyframes dropSuccess {
from {
transform: scale(0.95);
}
to {
transform: scale(1);
}
}
Такая визуализация помогает пользователю мгновенно понимать текущий этап взаимодействия.
При перетаскивании Shopify Draggable создаёт специальный элемент — mirror, визуальную копию исходного объекта. Он следует за курсором и отображает перемещаемый элемент.
Особенности mirror-элемента:
position: fixedПример настройки внешнего вида:
.draggable-mirror {
pointer-events: none;
z-index: 9999;
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
}
Эта визуализация делает перемещение более плавным и интуитивным.
Контейнеры, принимающие элементы, могут менять внешний вид при наведении перетаскиваемого объекта.
Для этого используется класс draggable--over.
Пример:
.dropzone {
border: 2px dashed #ccc;
transition: background 0.2s;
}
.dropzone.draggable--over {
background: #e8f0ff;
border-color: #5b8cff;
}
Такое поведение особенно важно в интерфейсах с большим количеством зон.
При сортировке элементов важно показать точное место вставки.
Библиотека предоставляет плагин:
Он автоматически управляет позиционированием элементов внутри контейнера.
Инициализация:
import {Sortable} from '@shopify/draggable';
const sortable = new Sortable(document.querySelectorAll('.list'), {
draggable: '.item'
});
Для визуализации позиции можно использовать разделители или отступы:
.list .item {
transition: transform 0.15s ease;
}
.list .item.draggable--over {
border-top: 3px solid #3a7afe;
}
Элемент, над которым находится курсор, показывает потенциальную точку вставки.
Иногда требуется показать пользователю, что элемент нельзя разместить в определённой области.
Это реализуется через обработчики событий.
Событие:
drag:over
Пример:
draggable.on('drag:over', (event) => {
const container = event.overContainer;
if (!container.classList.contains('allowed')) {
container.classList.add('invalid-drop');
}
});
CSS-оформление:
.invalid-drop {
background: #ffe9e9;
border-color: #ff5b5b;
}
Пользователь сразу видит ограничение.
Если элемент отпускается вне допустимого контейнера, он возвращается на исходную позицию.
Этот процесс можно анимировать.
Пример:
.draggable--source {
transition: transform 0.25s ease;
}
Дополнительная визуализация:
.draggable-return {
animation: returnAnimation 0.3s ease;
}
@keyframes returnAnimation {
0% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
Такая анимация делает поведение интерфейса более понятным.
В момент начала перетаскивания элемент получает состояние drag start.
Событие:
drag:start
Обработчик:
draggable.on('drag:start', (event) => {
event.source.classList.add('active-drag');
});
CSS:
.active-drag {
opacity: 0.5;
cursor: grabbing;
}
Сразу становится ясно, какой элемент участвует во взаимодействии.
Когда пользователь отпускает элемент, происходит событие:
drag:stop
Обработчик:
draggable.on('drag:stop', (event) => {
event.source.classList.remove('active-drag');
});
Также можно добавить эффект подтверждения.
.drop-success {
animation: success 0.25s ease;
}
@keyframes success {
0% { background: #eaffea; }
100% { background: transparent; }
}
В настройках библиотеки можно указать собственные классы состояний.
Пример конфигурации:
const draggable = new Draggable(document.querySelectorAll('.container'), {
draggable: '.item',
classes: {
'mirror': 'drag-mirror',
'source:dragging': 'dragging-source',
'container:over': 'container-over'
}
});
Это позволяет:
При сортировке длинных списков полезно показывать направление движения.
Реализация через события:
sortable:sorted
Пример:
sortable.on('sortable:sorted', (event) => {
const direction = event.oldIndex < event.newIndex ? 'down' : 'up';
event.dragEvent.source.classList.add(`move-${direction}`);
});
CSS:
.move-up {
animation: moveUp 0.2s ease;
}
.move-down {
animation: moveDown 0.2s ease;
}
@keyframes moveUp {
from { transform: translateY(-5px); }
to { transform: translateY(0); }
}
@keyframes moveDown {
from { transform: translateY(5px); }
to { transform: translateY(0); }
}
Такой подход усиливает ощущение физического перемещения элементов.
В сложных интерфейсах удобно выделять контейнер, с которым происходит взаимодействие.
События:
drag:enterdrag:leaveПример:
draggable.on('drag:enter', (event) => {
event.container.classList.add('active-container');
});
draggable.on('drag:leave', (event) => {
event.container.classList.remove('active-container');
});
CSS:
.active-container {
outline: 2px solid #4c7eff;
}
Контейнер становится визуально активным.
Для качественной визуализации состояний важны CSS-переходы.
Рекомендуемые свойства для анимации:
transformopacitybox-shadowbackground-colorПример:
.item {
transition:
transform 0.15s ease,
background 0.15s ease,
box-shadow 0.15s ease;
}
Использование transform предпочтительно, поскольку:
Некоторые элементы могут быть временно недоступны для перемещения.
CSS-индикация:
.item.locked {
opacity: 0.4;
cursor: not-allowed;
}
JS-проверка:
draggable.on('drag:start', (event) => {
if (event.source.classList.contains('locked')) {
event.cancel();
}
});
Визуальный сигнал предотвращает ошибки пользователя.
Комбинация состояний позволяет строить богатые интерфейсы:
Например, доска задач:
Все эти эффекты реализуются через комбинацию:
Система состояний Shopify Draggable предоставляет полный контроль над визуальной обратной связью интерфейса перетаскивания.