Библиотека Shopify Draggable предоставляет мощный инструментарий для работы с перетаскиваемыми элементами в веб-интерфейсах. Одним из ключевых аспектов пользовательского опыта является плавность перемещения элементов и визуальная обратная связь, которую обеспечивают transitions и animations. Эти механизмы позволяют создать ощущение естественности и интерактивности при взаимодействии с элементами списка, сетки или канбан-доски.
Shopify Draggable не накладывает ограничения на использование CSS-переходов. Наиболее часто применяются свойства transform, opacity, top, left и height/width, так как они наиболее оптимизированы для производительности в современных браузерах.
Пример добавления плавного смещения:
.draggable {
transition: transform 0.3s ease, opacity 0.2s ease;
}
Здесь:
transform 0.3s ease обеспечивает плавное перемещение
элемента при изменении его координат через Draggable.opacity 0.2s ease позволяет сделать
появление/исчезновение более естественным.Важный момент: при использовании CSS transitions с Draggable
необходимо учитывать, что библиотека сама управляет координатами
элементов через inline styles с помощью
transform: translate3d(x, y, 0). Поэтому лучше избегать
одновременной анимации top/left, чтобы не
создавать конфликты рендеринга.
Для sortable контейнеров Draggable предоставляет встроенные хуки, позволяющие реализовать анимацию перестановки элементов. Основные события:
sortable:sorted — вызывается после завершения
сортировки.sortable:sort — во время движения элемента.sortable:start и sortable:stop — начало и
завершение перетаскивания.Пример плавной анимации перестановки:
const container = document.querySelector('.sortable-container');
const sortable = new Draggable.Sortable(container, {
draggable: '.draggable',
mirror: {
constrainDimensions: true,
},
});
sortable.on('sortable:sort', (event) => {
const {oldIndex, newIndex, source} = event;
// Добавление CSS-класса для плавного перемещения
source.classList.add('animating');
requestAnimationFrame(() => {
source.classList.remove('animating');
});
});
И соответствующий CSS:
.draggable.animating {
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
Использование requestAnimationFrame гарантирует корректное применение анимации без мерцаний и заиканий при изменении DOM.
Draggable создает отдельный элемент mirror для
перетаскивания (mirror: true по умолчанию). Этот элемент
копирует внешний вид оригинала и движется поверх интерфейса, что
позволяет визуально отделить процесс перемещения от реального DOM.
transform.transform самого mirror:.draggable-mirror {
transition: transform 0.2s ease;
}
sortable.on('drag:start', (event) => {
event.data.mirror.style.opacity = '0.8';
});
sortable.on('drag:stop', (event) => {
event.data.mirror.style.opacity = '';
});
Метод FLIP (First, Last, Invert, Play) позволяет создавать плавные перестановки элементов без резких скачков. Draggable совместим с этим подходом через вычисление начальной и конечной позиции элементов.
Пример:
sortable.on('sortable:sorted', ({oldIndex, newIndex, source, containers}) => {
const firstRect = source.getBoundingClientRect();
// DOM уже обновлен
const lastRect = source.getBoundingClientRect();
const invertX = firstRect.left - lastRect.left;
const invertY = firstRect.top - lastRect.top;
source.style.transform = `translate(${invertX}px, ${invertY}px)`;
requestAnimationFrame(() => {
source.style.transition = 'transform 300ms ease';
source.style.transform = '';
});
});
Этот метод позволяет добиться эффекта «элемент плавно перемещается на новое место», сохраняя высокую производительность.
Для достижения более динамичных и естественных переходов можно использовать cubic-bezier кривые. Например:
.draggable {
transition: transform 0.35s cubic-bezier(0.25, 0.8, 0.25, 1);
}
ease-in-out – замедление в начале и в конце.cubic-bezier(0.25, 1, 0.5, 1) – создаёт эффект
«отскока».Можно комбинировать mirror-анимации, FLIP, opacity transitions и scale эффекты. Пример:
sortable.on('drag:start', ({data}) => {
data.mirror.style.transition = 'transform 0.2s ease, opacity 0.2s ease';
data.mirror.style.opacity = '0.7';
data.mirror.style.transform += ' scale(1.05)';
});
sortable.on('drag:stop', ({data}) => {
data.mirror.style.transition = 'transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.25s';
data.mirror.style.opacity = '1';
data.mirror.style.transform = data.mirror.style.transform.replace(' scale(1.05)', '');
});
Такой подход создаёт ощущение «приподнятого» элемента, который плавно возвращается в исходное состояние после завершения перетаскивания.
Понимание и правильное сочетание transitions, mirror-анимаций и FLIP-подхода позволяет создавать интерфейсы, где перемещение элементов ощущается естественным, отзывчивым и визуально привлекательным.