В библиотеке Shopify Draggable событие
drag:move является ключевым для отслеживания перемещения
элемента во время перетаскивания. Оно срабатывает непрерывно при каждом
изменении позиции draggable элемента и позволяет
динамически реагировать на движение пользователя, обновлять интерфейс
или взаимодействовать с другими компонентами страницы.
Синтаксис регистрации обработчика выглядит следующим образом:
const draggable = new Draggable(document.querySelectorAll('.container'), {
draggable: '.item'
});
draggable.on('drag:move', (event) => {
console.log(event);
});
В объекте event доступны следующие основные
свойства:
source — DOM-элемент, который перетаскивается.sensorEvent — оригинальное событие мыши или сенсорного
экрана, содержащее координаты clientX и
clientY.over — элемент, над которым в данный момент находится
перетаскиваемый объект (если настроен sortable или
swap animation).mirror — элемент-макет, отображаемый поверх интерфейса
во время перетаскивания.originalEvent — исходное нативное событие браузера
(MouseEvent или TouchEvent).Для отслеживания позиции элемента чаще всего используется сочетание
event.sensorEvent.clientX и
event.sensorEvent.clientY. Эти координаты обновляются при
каждом срабатывании события drag:move.
Пример динамического отслеживания позиции и вывода в консоль:
draggable.on('drag:move', (event) => {
const x = event.sensorEvent.clientX;
const y = event.sensorEvent.clientY;
console.log(`Текущая позиция: x=${x}, y=${y}`);
});
Если требуется более точное позиционирование относительно контейнера,
можно использовать getBoundingClientRect:
const container = document.querySelector('.container');
draggable.on('drag:move', (event) => {
const rect = container.getBoundingClientRect();
const x = event.sensorEvent.clientX - rect.left;
const y = event.sensorEvent.clientY - rect.top;
console.log(`Позиция относительно контейнера: x=${x}, y=${y}`);
});
mirror для визуальных эффектовЭлемент mirror создается Draggable автоматически и
является клоном исходного элемента, который следует за курсором. Через
drag:move можно изменять его стили динамически:
draggable.on('drag:move', (event) => {
const mirror = event.mirror;
mirror.style.transform = `rotate(${event.sensorEvent.clientX / 5}deg)`;
});
Это позволяет создавать сложные анимации, изменять прозрачность или масштаб перетаскиваемого объекта в реальном времени.
Событие drag:move можно использовать для
ограничения движения по определённой оси или внутри
контейнера:
draggable.on('drag:move', (event) => {
const mirror = event.mirror;
const rect = event.source.parentElement.getBoundingClientRect();
let x = event.sensorEvent.clientX - rect.left;
let y = event.sensorEvent.clientY - rect.top;
// Ограничение по вертикали
y = Math.max(0, Math.min(rect.height - mirror.offsetHeight, y));
// Ограничение по горизонтали
x = Math.max(0, Math.min(rect.width - mirror.offsetWidth, x));
mirror.style.transform = `translate(${x}px, ${y}px)`;
});
Такой подход позволяет создавать drag-and-drop сетки, ограничивать перемещение внутри заданной области и комбинировать с кастомными визуальными эффектами.
Событие drag:move тесно связано с другими событиями:
drag:start — инициализация перемещения.drag:over — объект перемещается над другим
элементом.drag:stop — завершение перемещения и окончательное
позиционирование.Типичная цепочка использования:
draggable.on('drag:start', (event) => {
console.log('Начало перетаскивания', event.source);
});
draggable.on('drag:move', (event) => {
console.log('Движение элемента', event.sensorEvent.clientX, event.sensorEvent.clientY);
});
draggable.on('drag:stop', (event) => {
console.log('Элемент сброшен', event.source);
});
Такое разделение позволяет отдельно управлять логикой отображения, ограничениями движения и обновлением данных модели.
mirror для эффекта “парящего” элемента.При интенсивном использовании drag:move важно учитывать,
что событие вызывается десятки раз в секунду. Рекомендуется:
requestAnimationFrame для обновления
стилей:let ticking = false;
draggable.on('drag:move', (event) => {
if (!ticking) {
requestAnimationFrame(() => {
event.mirror.style.transform = `translate(${event.sensorEvent.clientX}px, ${event.sensorEvent.clientY}px)`;
ticking = false;
});
ticking = true;
}
});
Такой подход снижает нагрузку на браузер и обеспечивает плавное перетаскивание даже при множестве элементов.
Эти техники демонстрируют, как
drag:move становится центром контроля над
перемещением элементов и позволяет создавать интерактивные интерфейсы с
высокой точностью и гибкостью.