Основы работы с жестами

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


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

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

<script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
npm install interactjs

После подключения можно инициализировать элемент для взаимодействия:

interact('.draggable')
  .draggable({
    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);
      }
    }
  });

Ключевой момент: event.dx и event.dy содержат смещение мыши или пальца по осям X и Y, что позволяет плавно перемещать элемент.


События жестов

Interact.js выделяет несколько типов событий, связанных с жестами:

  1. dragstart – срабатывает в момент начала перетаскивания.
  2. dragmove – срабатывает при каждом изменении позиции элемента.
  3. dragend – вызывается при окончании перетаскивания.
  4. gesturestart – фиксирует начало мультитач-жеста (например, сжатие или растяжение).
  5. gesturemove – срабатывает при каждом изменении жеста.
  6. gestureend – фиксирует завершение жеста.
interact('.gesture-element')
  .gesturable({
    listeners: {
      start(event) {
        console.log('Жест начался');
      },
      move(event) {
        const scale = parseFloat(event.target.getAttribute('data-scale')) || 1;
        const newScale = scale * (1 + event.ds);

        event.target.style.transform = `scale(${newScale})`;
        event.target.setAttribute('data-scale', newScale);
      },
      end(event) {
        console.log('Жест завершён');
      }
    }
  });

Объяснение ключевых свойств события:

  • event.ds — изменение масштаба между текущим и предыдущим кадром.
  • event.da — изменение угла поворота между кадрами (в градусах).
  • event.touches — массив всех точек касания на момент события.

Сочетание перетаскивания и жестов

Interact.js позволяет комбинировать draggable и gesturable для одного элемента:

interact('.multi-interact')
  .draggable({
    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;
        const scale = parseFloat(target.getAttribute('data-scale')) || 1;

        target.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;
        target.setAttribute('data-x', x);
        target.setAttribute('data-y', y);
      }
    }
  })
  .gesturable({
    listeners: {
      move(event) {
        const target = event.target;
        const scale = (parseFloat(target.getAttribute('data-scale')) || 1) * (1 + event.ds);

        const x = parseFloat(target.getAttribute('data-x')) || 0;
        const y = parseFloat(target.getAttribute('data-y')) || 0;

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

Особенность: данные о трансформации можно хранить прямо в атрибутах DOM (data-x, data-y, data-scale), что упрощает синхронизацию нескольких эффектов одновременно.


Ограничение жестов

Interact.js предоставляет возможность задавать ограничения для движения и масштабирования:

interact('.draggable')
  .draggable({
    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);
      }
    }
  });

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


Настройка чувствительности жестов

Для мультитач-жестов можно управлять порогами срабатывания и масштабированием:

interact('.gesture-element')
  .gesturable({
    listeners: {
      move(event) {
        const scaleFactor = 1 + event.ds * 0.5; // уменьшение чувствительности
        const currentScale = parseFloat(event.target.getAttribute('data-scale')) || 1;
        const newScale = currentScale * scaleFactor;

        event.target.style.transform = `scale(${newScale})`;
        event.target.setAttribute('data-scale', newScale);
      }
    }
  });

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


Взаимодействие с событиями мыши и касания

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

interact('.draggable').draggable({
  pointerEvents: {
    mouse: true,
    touch: true,
    pen: true
  }
});

Это обеспечивает одинаковое поведение на сенсорных и десктопных устройствах.


Обработка нескольких элементов

Библиотека позволяет инициализировать сразу несколько элементов через селекторы:

interact('.draggable, .resizable')
  .draggable({ /* конфигурация */ })
  .gesturable({ /* конфигурация */ });

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


Практические рекомендации

  • Хранение координат и масштаба в data-* атрибутах обеспечивает консистентность состояния при динамических изменениях DOM.
  • Использование модификаторов (restrict, snap) позволяет создавать точные и предсказуемые интерфейсы.
  • Комбинирование draggable и gesturable позволяет реализовать полноценные мультитач-интеракции, включая масштабирование, вращение и перемещение одновременно.
  • Внимательно контролировать обработку событий, чтобы избежать “дребезга” или неожиданных изменений при быстром перемещении или масштабировании.

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