Перетаскивание между фреймами

Dragula — это библиотека для реализации перетаскивания элементов на странице с минимальной настройкой. Она предоставляет простой API для работы с drag-and-drop, позволяя перемещать элементы внутри контейнеров и между ними. Базовой единицей работы являются контейнеры (containers) и элементы (draggable items). Каждый контейнер — это DOM-узел, который может содержать перемещаемые элементы.

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

const containers = [document.getElementById('frame1'), document.getElementById('frame2')];
const drake = dragula(containers);

Здесь drake — это объект, который обеспечивает все события и методы для управления перетаскиванием.


Работа с контейнерами

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

Основные моменты при работе с контейнерами:

  • Контейнеры должны быть DOM-узлами (например, <div> или <ul>).
  • Можно добавлять новые контейнеры после инициализации с помощью метода drake.containers.push(newContainer).
  • Элементы перетаскиваются только внутри контейнеров, добавленных в инстанс.
const newContainer = document.getElementById('frame3');
drake.containers.push(newContainer);

Настройка перетаскиваемых элементов

Dragula позволяет гибко управлять, какие элементы могут быть перетащены и куда их можно помещать.

Фильтрация элементов

Метод moves позволяет задать условие, при котором элемент можно перетащить:

const drake = dragula(containers, {
  moves: function (el, source, handle, sibling) {
    return handle.classList.contains('handle');
  }
});
  • el — сам элемент, который будет перемещаться.
  • source — контейнер, из которого элемент перемещается.
  • handle — элемент, на который пользователь кликает для начала перетаскивания.
  • sibling — элемент, перед которым вставляется перетаскиваемый элемент.

Контроль допустимых контейнеров

Метод accepts определяет, можно ли вставить элемент в конкретный контейнер:

const drake = dragula(containers, {
  accepts: function (el, target, source, sibling) {
    return target.id !== 'frame2'; // запрещаем вставку в frame2
  }
});

События Dragula

Dragula имеет богатую систему событий, которые помогают отслеживать состояние перетаскивания.

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

  • drag — элемент начал перетаскиваться.
  • dragend — завершение перетаскивания.
  • drop — элемент вставлен в новый контейнер.
  • over — элемент находится над контейнером.
  • out — элемент покинул контейнер.
  • cancel — отмена перетаскивания.

Пример подписки на события:

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

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

Особенности событий:

  • События over и out полезны для визуального подсвечивания контейнеров при наведении.
  • drop срабатывает только при успешном завершении операции.
  • cancel может быть вызван программно, если перетаскивание нужно отменить.

Перетаскивание между фреймами

Dragula поддерживает работу с элементами между несколькими контейнерами, что позволяет реализовать сложные интерфейсы типа kanban-досок или drag-and-drop списков.

Пошаговый процесс перемещения:

  1. Создание массива контейнеров, которые участвуют в перетаскивании.
  2. Инициализация Dragula с этим массивом.
  3. Настройка правил перемещения через moves и accepts.
  4. Подписка на события для визуальной обратной связи.
const frames = [
  document.getElementById('frame1'),
  document.getElementById('frame2'),
  document.getElementById('frame3')
];

const drake = dragula(frames, {
  moves: (el, source, handle) => handle.classList.contains('handle'),
  accepts: (el, target) => !target.classList.contains('locked')
});

drake.on('drop', (el, target) => {
  console.log(`Элемент ${el.textContent} перемещён в контейнер ${target.id}`);
});

Особенности перетаскивания между фреймами:

  • Dragula копирует ссылку на элемент, не создавая его дубликат.
  • Если контейнер или элемент динамически создаются после инициализации, их нужно добавить в массив контейнеров или использовать drake.containers.push.
  • Перетаскивание полностью контролируется событиями, что позволяет реализовать кастомную логику, например, сортировку или ограничения по категориям.

Работа с анимацией и стилями

Для улучшения UX часто применяют визуальные эффекты. Dragula по умолчанию использует класс gu-mirror, который создается при перетаскивании элемента.

  • gu-mirror — это временный DOM-элемент, отображаемый при перетаскивании.
  • Его стили можно настраивать через CSS:
.gu-mirror {
  position: fixed;
  margin: 0;
  z-index: 9999;
  opacity: 0.8;
  border: 2px dashed #333;
}
  • gu-transit — класс, добавляемый к элементу, пока он перетаскивается. Можно использовать для плавного скрытия или подсветки.

Динамическое управление контейнерами

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

const dynamicContainer = document.createElement('div');
dynamicContainer.id = 'dynamic';
document.body.appendChild(dynamicContainer);
drake.containers.push(dynamicContainer);

Для удаления контейнера достаточно удалить его из массива drake.containers:

const index = drake.containers.indexOf(dynamicContainer);
if (index > -1) drake.containers.splice(index, 1);

Это гарантирует, что Dragula перестанет отслеживать элементы в этом контейнере.


Интеграция с другими библиотеками и фреймворками

Dragula легко интегрируется с React, Vue и Angular через рефы или директивы, предоставляя нативный drag-and-drop без использования тяжелых решений.

  • В React контейнеры передаются через ref.
  • В Vue можно использовать директивы для инициализации Dragula на mounted-хук.
  • В Angular контейнеры и события можно связывать через ViewChild и сервисы.

Эта гибкость делает Dragula идеальным выбором для проектов с множественными фреймами и сложной логикой перетаскивания.