Целевые элементы и селекторы

Interact.js — это библиотека, предоставляющая мощные средства для создания интерактивных элементов на веб-странице: перетаскивания, масштабирования, вращения и управления жестами. Центральным понятием при работе с этой библиотекой являются целевые элементы и селекторы, которые позволяют точно определить, какие элементы будут интерактивными, и каким образом с ними будет происходить взаимодействие.


Определение целевых элементов

Целевой элемент — это HTML-элемент, к которому применяется интерактивность. В Interact.js целевой элемент передаётся функции interact():

interact('.draggable')
  .draggable({
    inertia: true,
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    listeners: {
      move: dragMoveListener
    }
  });

В данном примере целевыми элементами являются все элементы с классом draggable. Функция interact() принимает CSS-селектор, DOM-элемент или NodeList, что обеспечивает гибкость в выборе элементов для взаимодействия.

Возможные типы целевых элементов:

  1. CSS-селекторы Позволяют применять интерактивность ко множеству элементов сразу. Примеры: .draggable, #item-1, div.card.

  2. DOM-элемент Прямое указание элемента через document.getElementById или document.querySelector.

    const element = document.getElementById('box');
    interact(element).draggable({ ... });
  3. NodeList или массив элементов Можно передать сразу несколько элементов:

    const elements = document.querySelectorAll('.item');
    interact(elements).draggable({ ... });

Использование селекторов для точной фильтрации

Селекторы в Interact.js работают аналогично CSS-селекторам, но есть возможность комбинировать их с дополнительными условиями через метод .ignoreFrom() и .allowFrom(). Это позволяет исключать или включать определённые подэлементы при взаимодействии.

  • allowFrom(selector) — разрешает взаимодействие только с указанными потомками целевого элемента.

    interact('.container')
      .draggable({
        allowFrom: '.handle', // перетаскивание доступно только с элементов с классом handle
        listeners: { move: dragMoveListener }
      });
  • ignoreFrom(selector) — запрещает взаимодействие с указанными потомками целевого элемента.

    interact('.container')
      .draggable({
        ignoreFrom: 'input, button', // игнорируются поля ввода и кнопки
        listeners: { move: dragMoveListener }
      });

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


Применение селекторов к динамически создаваемым элементам

Interact.js позволяет работать с элементами, которые создаются динамически после загрузки страницы. Если селектор передан строкой CSS, библиотека будет автоматически отслеживать новые совпадающие элементы. Важно использовать CSS-селекторы, а не NodeList, для динамических элементов, так как NodeList фиксирует элементы на момент вызова interact().

interact('.dynamic-draggable')
  .draggable({ listeners: { move: dragMoveListener } });

// При добавлении нового элемента <div class="dynamic-draggable"></div>
// он автоматически становится интерактивным

Ограничения и лучшие практики

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

  2. Минимизация количества целевых элементов Каждый целевой элемент создаёт собственный обработчик событий. Для производительности важно не назначать интерактивность на слишком большое количество элементов без необходимости.

  3. Комбинация селекторов Можно использовать сложные CSS-селекторы для точного попадания в нужные элементы:

    interact('ul li.draggable > span.handle').draggable({ ... });
  4. Согласованность структуры DOM Методы allowFrom и ignoreFrom работают корректно только если структура DOM остаётся предсказуемой. Если элементы будут перемещаться или меняться динамически, нужно проверять селекторы.


Примеры практического использования

1. Перетаскивание карточек с ограничением по контейнеру

interact('.card')
  .draggable({
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: '.board',
        endOnly: true
      })
    ],
    listeners: {
      move: function (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);
      }
    }
  });

2. Масштабирование и вращение конкретного элемента с ручками

interact('.resizable')
  .resizable({
    edges: { left: true, right: true, bottom: true, top: true },
    listeners: {
      move(event) {
        const target = event.target;
        let x = (parseFloat(target.getAttribute('data-x')) || 0);
        let y = (parseFloat(target.getAttribute('data-y')) || 0);

        target.style.width = `${event.rect.width}px`;
        target.style.height = `${event.rect.height}px`;

        x += event.deltaRect.left;
        y += event.deltaRect.top;

        target.style.transform = `translate(${x}px, ${y}px)`;
        target.setAttribute('data-x', x);
        target.setAttribute('data-y', y);
      }
    },
    modifiers: [
      interact.modifiers.restrictEdges({
        outer: 'parent'
      })
    ]
  });

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


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