Collidable

Collidable — это модуль в библиотеке Shopify Draggable, который отвечает за обнаружение столкновений элементов во время перетаскивания и позволяет создавать динамическое взаимодействие между draggable-элементами и другими объектами на странице. Основное назначение — определить, когда перетаскиваемый элемент «входит» в область другого элемента, и реагировать на это событие соответствующим образом.


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

Для использования Collidable необходимо подключить его при создании экземпляра Draggable:

import { Draggable, Plugins } from '@shopify/draggable';

const draggable = new Draggable(document.querySelectorAll('.draggable-container'), {
  draggable: '.draggable-item',
  plugins: [Plugins.Collidable]
});

Здесь Plugins.Collidable добавляет функциональность коллизий в процесс drag-and-drop.


Основные опции Collidable

Collidable поддерживает несколько ключевых опций, которые позволяют тонко настраивать поведение:

  • collidables – селекторы элементов, с которыми нужно проверять столкновения.
  • classes – CSS-классы, которые будут добавлены элементу при столкновении.
  • mirror – объект mirror (отражение перетаскиваемого элемента), влияющий на расчёт коллизий.

Пример настройки:

const draggable = new Draggable(document.querySelectorAll('.draggable-container'), {
  draggable: '.draggable-item',
  plugins: [Plugins.Collidable],
  collidables: '.collidable-item',
  classes: {
    collidable: 'is-colliding',
    snapping: 'is-snapping'
  }
});
  • collidable — добавляется к элементу, с которым произошло столкновение.
  • snapping — применяется к перетаскиваемому элементу, когда он находится в зоне столкновения.

События Collidable

Collidable генерирует ряд событий, которые позволяют отслеживать жизненный цикл столкновений:

  1. collidable:over — перетаскиваемый элемент вошёл в область другого элемента.
  2. collidable:out — перетаскиваемый элемент покинул область другого элемента.
  3. collidable:stop — завершение столкновения (например, отпускание элемента на коллайдер).

Пример обработки событий:

draggable.on('collidable:over', (event) => {
  const dragged = event.dragged;
  const colliding = event.colliding;
  console.log(`Элемент ${dragged.textContent} столкнулся с ${colliding.textContent}`);
});

draggable.on('collidable:out', (event) => {
  console.log(`Элемент ${event.dragged.textContent} покинул ${event.colliding.textContent}`);
});

Каждое событие содержит полезные свойства:

  • event.dragged — элемент, который перетаскивают.
  • event.colliding — элемент, с которым произошло столкновение.
  • event.sensorEvent — исходное событие мыши или касания.

Алгоритм работы Collidable

Collidable использует геометрические расчёты bounding box для определения пересечения элементов:

  1. Вычисляются границы перетаскиваемого элемента (mirror-элемент при drag).
  2. Вычисляются границы потенциальных коллайдеров (collidables).
  3. Проверяется пересечение прямоугольников.
  4. В зависимости от результата, добавляются или удаляются классы, вызываются события.

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


Snap-to-Element и визуальные эффекты

Одна из часто используемых функций Collidablesnap-to-element, когда перетаскиваемый элемент «прилипает» к границе другого элемента.

Пример:

draggable.on('collidable:over', (event) => {
  const mirror = draggable.getPlugin('Mirror').mirror;
  const targetRect = event.colliding.getBoundingClientRect();
  mirror.style.transform = `translate(${targetRect.left}px, ${targetRect.top}px)`;
});

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


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

  • Ограничивать количество коллайдеров — большое количество элементов с проверкой коллизий может снижать FPS.
  • Использовать CSS-классы вместо постоянных вычислений — для визуальных эффектов добавлять/удалять классы, а не пересчитывать координаты каждый кадр.
  • Обновлять список коллайдеров при динамических изменениях DOM — если элементы добавляются или удаляются, collidables нужно переинициализировать.

Расширенные возможности

  • Collidable можно комбинировать с другими плагинами Draggable, например, SwapAnimation для анимации перестановок элементов при столкновении.
  • Поддержка вложенных контейнеров: коллизии могут проверяться внутри нескольких уровней DOM, если правильно настроить селекторы.
  • Интеграция с Mirror plugin позволяет перетаскиваемому элементу оставаться визуально на месте при сложных пересечениях.

Практический пример: sortable список с Collidable

const sortable = new Draggable(document.querySelectorAll('.list'), {
  draggable: '.list-item',
  plugins: [Plugins.Collidable]
});

sortable.on('collidable:over', (event) => {
  const dragged = event.dragged;
  const target = event.colliding;
  target.parentNode.insertBefore(dragged, target.nextSibling);
});

В этом примере перетаскиваемый элемент автоматически вставляется после элемента, с которым произошло столкновение, создавая динамический сортируемый список.


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