Обертки и компоненты

Interact.js предоставляет гибкий механизм для создания интерактивных элементов через обертки и компоненты, позволяя управлять перетаскиванием, масштабированием и взаимодействием с DOM без прямого вмешательства в низкоуровневые события.

Обертки (wrappers)

Обертка — это специальный объект, который инкапсулирует DOM-элемент и предоставляет интерфейс для управления его интерактивными свойствами. Основная цель обертки — отделить логику взаимодействия от структуры документа.

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

const element = document.getElementById('drag-item');

const wrapper = interact(element)
  .draggable({
    inertia: true,
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    listeners: {
      move(event) {
        const target = event.target;
        const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
        const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;

        target.style.transform = `translate(${x}px, ${y}px)`;
        target.setAttribute('data-x', x);
        target.setAttribute('data-y', y);
      }
    }
  });

Ключевые моменты:

  • interact(element) возвращает обертку для указанного DOM-элемента.
  • Обертка позволяет применять несколько типов взаимодействий одновременно: draggable, resizable, gesturable.
  • Использование modifiers обеспечивает контроль над поведением элементов при перемещении или масштабировании.

Компоненты (components)

Компонент в Interact.js — это совокупность настроек и слушателей событий, которые можно многократно применять к разным оберткам. Это позволяет создавать повторно используемые интерактивные модули.

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

interact.createSnapComponent({
  targets: '.snap-target',
  snap: {
    targets: [
      interact.snappers.grid({ x: 50, y: 50 })
    ],
    range: Infinity,
    relativePoints: [{ x: 0.5, y: 0.5 }]
  }
});

Особенности компонентов:

  • Компоненты могут включать собственные модификаторы, перехватчики событий и обработчики.
  • Позволяют стандартизировать поведение нескольких элементов без дублирования кода.
  • Интегрируются с обертками через цепочку методов interact(element).use(component).

Пример использования компонента с оберткой:

const draggableComponent = interact.draggable({
  listeners: { move: dragMoveListener },
  modifiers: [interact.modifiers.restrictRect({ restriction: 'parent' })]
});

interact('.item').use(draggableComponent);

Связь оберток и компонентов

Обертка является контейнером для одного или нескольких компонентов. При вызове методов обертки компоненты регистрируются внутри неё и начинают обрабатывать события:

  1. Инициализация обертки: interact(element)
  2. Применение компонентов: wrapper.use(component)
  3. Обработка событий: компоненты подписаны на события обертки (dragstart, dragmove, dragend)

Такое разделение позволяет:

  • Легко заменять или обновлять компоненты без изменения обертки.
  • Управлять сложными интерактивными сценариями через комбинацию простых модулей.

Расширяемость через собственные компоненты

Interact.js поддерживает создание кастомных компонентов. Для этого необходимо реализовать объект с методом init, который будет принимать обертку и регистрировать слушатели событий.

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

const highlightOnDrag = {
  init(wrapper) {
    wrapper.on('dragstart', (event) => {
      event.target.style.border = '2px solid red';
    });
    wrapper.on('dragend', (event) => {
      event.target.style.border = '';
    });
  }
};

interact('.draggable').use(highlightOnDrag);

Преимущества собственного компонента:

  • Полный контроль над поведением элемента без изменения глобальных настроек.
  • Возможность повторного использования логики в разных обертках.
  • Совместимость с существующими модификаторами и слушателями.

Модификаторы и события как части компонентов

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

  • Ограничением перемещения и размеров (restrictRect, restrictEdges)
  • Привязкой к сетке (snap, grid)
  • Реакцией на жесты мультитач (gesturable)

Пример комбинации модификаторов в компоненте:

interact('.resizable')
  .resizable({
    edges: { left: true, right: true, bottom: true, top: true },
    modifiers: [
      interact.modifiers.restrictSize({ min: { width: 50, height: 50 } }),
      interact.modifiers.snapSize({ targets: [interact.snappers.grid({ x: 20, y: 20 })] })
    ],
    listeners: {
      move(event) {
        let { x, y } = event.target.dataset;
        event.target.style.width  = `${event.rect.width}px`;
        event.target.style.height = `${event.rect.height}px`;
      }
    }
  });

Рекомендации по структуре кода

  • Создавать обертку для каждого интерактивного элемента.
  • Выносить повторяющиеся конфигурации в отдельные компоненты.
  • Использовать модификаторы для управления ограничениями и привязками.
  • Объединять несколько компонентов для сложного поведения элементов.
  • Минимизировать прямое манипулирование стилями внутри слушателей, используя data-атрибуты и CSS-переменные для трансформаций.

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