Адаптивная стилизация

Dragula — это лёгкая библиотека для реализации drag-and-drop функционала в веб-приложениях на JavaScript. Она позволяет перетаскивать элементы между контейнерами и внутри одного контейнера, сохраняя при этом простоту подключения и минимальную настройку. Основная цель Dragula — предоставить разработчику интуитивно понятный API без необходимости писать сложные обработчики событий вручную.

Подключение и инициализация

Для использования Dragula достаточно подключить библиотеку через CDN или npm-пакет:

<script src="https://unpkg.com/dragula/dist/dragula.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/dragula/dist/dragula.min.css">

Инициализация выполняется очень просто:

const containers = [document.getElementById('left'), document.getElementById('right')];
const drake = dragula(containers);

В этом примере drake создаёт возможность перетаскивания элементов между двумя контейнерами left и right.

Основные методы и события

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

  • Методы:

    • drake.cancel() — отменяет текущее перетаскивание.
    • drake.remove() — удаляет элемент из DOM после перетаскивания.
    • drake.start() и drake.end() — программно запускают или завершают drag-сессию.
  • События:

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

События подписываются через метод on:

drake.on('drop', (el, target, source, sibling) => {
    console.log('Элемент перемещён:', el);
});

Конфигурация Dragula

Для адаптации поведения Dragula предусмотрены опции при инициализации:

  • moves — функция, определяющая, можно ли перемещать элемент. Возвращает true или false.
  • accepts — функция, определяющая, можно ли помещать элемент в конкретный контейнер.
  • copy — если true, элемент будет клонироваться при перетаскивании.
  • revertOnSpill — возвращает элемент на место, если он не был успешно помещён в контейнер.

Пример кастомной конфигурации:

const drake = dragula(containers, {
    moves: (el, source, handle, sibling) => handle.classList.contains('handle'),
    accepts: (el, target) => !target.classList.contains('no-drop'),
    copy: false,
    revertOnSpill: true
});

Здесь перемещать элементы можно только за «ручку» (handle), а помещать — только в контейнеры без класса no-drop.

Адаптивная стилизация элементов

Dragula по умолчанию добавляет классы, которые можно использовать для CSS-стилизации:

  • gu-mirror — элемент, который отображается во время перетаскивания.
  • gu-transit — элемент, который перемещается из исходного контейнера.
  • gu-hide — временно скрывает оригинальный элемент.

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

.gu-mirror {
    background-color: rgba(0, 123, 255, 0.3);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
    border-radius: 4px;
}

.gu-transit {
    opacity: 0.6;
}

Для адаптивного дизайна важно учитывать размер и позицию элементов на разных экранах. Можно динамически изменять стили через Jav * aScript:

drake.on('drag', (el) => {
    el.style.width = el.offsetWidth + 'px';
});

Это предотвращает «скачки» ширины при перетаскивании в контейнер меньшего размера.

Интеграция с CSS-фреймворками

Dragula легко совмещается с современными CSS-фреймворками, такими как Bootstrap или Tailwind. При этом можно использовать классы фреймворка для:

  • визуальных эффектов hover
  • анимации перемещения
  • адаптивной ширины и высоты

Пример с Tailwind:

.gu-mirror {
    @apply bg-blue-200 shadow-lg rounded-md;
}
.gu-transit {
    @apply opacity-60;
}

Перетаскивание с анимацией

Для плавного перемещения можно комбинировать Dragula с CSS-переходами:

.gu-transit, .gu-mirror {
    transition: transform 0.2s ease, opacity 0.2s ease;
}

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

Работа с динамическим содержимым

Если элементы добавляются в контейнеры динамически, Dragula может быть настроен на автообновление контейнеров:

const dynamicContainer = document.getElementById('dynamic');
drake.containers.push(dynamicContainer);

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

Сохранение состояния

Чтобы элементы оставались на своих местах после перезагрузки страницы, можно использовать локальное хранилище:

drake.on('drop', (el, target) => {
    const state = Array.from(target.children).map(e => e.id);
    localStorage.setItem(target.id, JSON.stringify(state));
});

При загрузке страницы:

const savedState = JSON.parse(localStorage.getItem('right'));
if (savedState) {
    savedState.forEach(id => document.getElementById(id) && right.appendChild(document.getElementById(id)));
}

Советы по производительности

  • Ограничивать количество контейнеров и элементов при больших DOM-структурах.
  • Минимизировать работу с рефлоу и repaint в CSS.
  • Использовать классы gu-mirror и gu-transit для анимации, вместо постоянного изменения inline-стилей.

Эта методика позволяет создавать адаптивные, интерактивные интерфейсы, которые корректно работают на различных устройствах, с плавной анимацией и минимальной нагрузкой на DOM. Dragula сочетает простоту использования с гибкостью настройки, что делает её мощным инструментом для реализации drag-and-drop функционала в современном JavaScript-приложении.