В библиотеке Shopify Draggable mirror —
это визуальная копия перетаскиваемого элемента, которая появляется во
время drag-события. Она обеспечивает пользователю визуальную обратную
связь о перемещении элемента, но по умолчанию mirror имеет простую
стилизацию, которая может не соответствовать дизайну интерфейса.
Настройка внешнего вида mirror элемента позволяет создавать более
гармоничный и удобный UX.
Перед стилизацией mirror элемента необходимо корректно инициализировать Draggable:
import { Draggable } from '@shopify/draggable';
const draggable = new Draggable(document.querySelectorAll('.draggable-container'), {
draggable: '.draggable-item',
mirror: {
constrainDimensions: true,
appendTo: 'body',
},
});
Параметр mirror.constrainDimensions: true заставляет
mirror сохранять размеры оригинального элемента, что упрощает визуальное
восприятие перемещения. appendTo определяет родительский
элемент, к которому будет добавлен mirror в DOM.
Mirror элемент создаётся динамически при начале drag-события и имеет
класс .draggable-mirror. Стили можно задавать через CSS или
программно через события Draggable.
.draggable-mirror {
background-color: rgba(255, 255, 255, 0.95);
border: 2px solid #3498db;
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
border-radius: 8px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
z-index: 9999;
pointer-events: none;
}
Особенности:
pointer-events: none предотвращает перехват событий
мыши mirror элементом.z-index позволяет mirror всегда находиться поверх
других элементов.transition делает движение плавным при обновлении
позиции.Draggable предоставляет события mirror:created и
mirror:destroy для динамической настройки mirror
элемента.
draggable.on('mirror:created', (event) => {
const mirror = event.mirror;
mirror.style.backgroundColor = '#f9f9f9';
mirror.style.border = '1px dashed #2ecc71';
mirror.style.padding = '10px';
mirror.style.transform = 'scale(1.05)';
mirror.style.transition = 'transform 0.1s ease';
});
Преимущества программного подхода:
Mirror элемент можно анимировать, создавая эффекты, улучшающие UX:
draggable.on('mirror:created', (event) => {
const mirror = event.mirror;
mirror.animate([
{ transform: 'scale(0.95)', opacity: 0.7 },
{ transform: 'scale(1)', opacity: 1 }
], {
duration: 150,
easing: 'ease-out'
});
});
Такой подход создаёт плавное появление mirror при начале drag-сессии.
Если оригинальный элемент имеет динамическую высоту или ширину, можно
использовать mirror.constrainDimensions: false и задавать
размеры через CSS или события:
draggable.on('mirror:created', (event) => {
const mirror = event.mirror;
mirror.style.width = `${event.source.offsetWidth}px`;
mirror.style.height = `${event.source.offsetHeight}px`;
});
Это обеспечивает точное соответствие размера mirror и исходного элемента, даже если размеры изменяются динамически.
Mirror элемент можно менять в зависимости от положения курсора или состояния drag:
draggable.on('drag:move', (event) => {
const mirror = event.sourceMirror;
if (event.over) {
mirror.style.boxShadow = '0 12px 24px rgba(0,0,0,0.3)';
} else {
mirror.style.boxShadow = '0 8px 16px rgba(0,0,0,0.2)';
}
});
Это позволяет выделять потенциальные цели drop, делая взаимодействие более наглядным.
pointer-events: none для mirror, чтобы
исключить конфликты с drag-событиями.Настройка mirror элемента — ключевой шаг для создания качественного drag-and-drop интерфейса. Правильное оформление, плавные анимации и соответствие дизайну значительно повышают удобство использования.