Анимации и переходы

Dragula — это легкая библиотека для реализации drag-and-drop на веб-страницах без сложной настройки. Для начала необходимо подключить библиотеку. Можно использовать CDN:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.3/dragula.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.3/dragula.min.js"></script>

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

<div id="container1" class="container">
    <div class="item">Элемент 1</div>
    <div class="item">Элемент 2</div>
</div>

<div id="container2" class="container">
    <div class="item">Элемент 3</div>
    <div class="item">Элемент 4</div>
</div>

Инициализация Dragula осуществляется через вызов функции dragula с массивом контейнеров:

dragula([document.getElementById('container1'), document.getElementById('container2')]);

Основные события Dragula

Dragula предоставляет несколько ключевых событий для контроля процесса перетаскивания:

  • drag — срабатывает при начале перетаскивания элемента.
  • drop — срабатывает после того, как элемент отпущен и помещен в контейнер.
  • over — элемент наведен на контейнер, в который может быть помещен.
  • out — элемент покидает контейнер при перетаскивании.
  • cloned — срабатывает при клонировании элемента (если включено копирование).

Пример привязки событий:

const drake = dragula([container1, container2]);

drake.on('drag', function (el) {
    el.style.opacity = '0.5';
});

drake.on('drop', function (el, target, source, sibling) {
    el.style.opacity = '1';
});

Настройка анимаций при перетаскивании

Dragula по умолчанию не содержит сложных анимаций, но можно добавлять плавные переходы с помощью CSS. Основная идея — использовать transition для всех свойств, которые меняются при drag-and-drop.

Пример базового CSS:

.container .item {
    transition: transform 0.3s ease, opacity 0.3s ease;
}

.container .gu-mirror {
    box-shadow: 0 4px 15px rgba(0,0,0,0.2);
    border-radius: 4px;
}

.container .gu-transit {
    opacity: 0.7;
}
  • .gu-mirror — элемент, который создается Dragula для перетаскиваемого объекта.
  • .gu-transit — класс, применяемый к элементу во время перемещения.
  • transition — задает плавное изменение позиции и прозрачности.

Плавное смещение элементов

Когда элемент перетаскивается, оставшиеся элементы автоматически сдвигаются. Чтобы сделать этот процесс более плавным, используют CSS-переходы:

.container .item {
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

Использование кривой Безье позволяет получить естественное ускорение и замедление элементов при перестановке.


Интеграция с библиотеками анимации

Dragula совместим с библиотеками вроде GSAP, что позволяет создавать сложные эффекты:

drake.on('drop', function (el, target) {
    gsap.to(el, { scale: 1.05, duration: 0.2, yoyo: true, repeat: 1 });
});

Здесь элемент увеличивается при отпускании и возвращается в нормальный размер, создавая визуально приятный эффект «подпрыгивания».


Настройка визуальной обратной связи

Для лучшего восприятия перетаскивания полезно изменять свойства элементов в процессе drag:

drake.on('over', function (el, container) {
    container.style.backgroundColor = '#f0f0f0';
});

drake.on('out', function (el, container) {
    container.style.backgroundColor = '';
});
  • Изменение цвета контейнера — подсказывает пользователю, куда можно переместить элемент.
  • Изменение прозрачности и тени — помогает выделить перетаскиваемый объект.

Использование moves и accepts для контроля анимации

С помощью опций moves и accepts можно настроить, какие элементы можно перетаскивать, а какие — куда помещать, что особенно полезно при сложных анимациях с разными контейнерами:

dragula([container1, container2], {
    moves: function(el, source, handle) {
        return handle.classList.contains('handle');
    },
    accepts: function(el, target) {
        return !target.classList.contains('no-drop');
    }
});

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


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

  • Минимизировать количество перерисовок DOM при перемещении.
  • Использовать transform: translate() вместо изменения top и left.
  • Добавлять will-change: transform для элементов, которые будут перемещаться.
  • Избегать анимации тяжелых CSS-свойств, таких как box-shadow, для большого числа элементов одновременно.
.container .item {
    will-change: transform, opacity;
}

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