Первый рабочий пример

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

CDN-подключение:

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

Установка через npm:

npm install @interactjs/interactjs

После установки через npm библиотеку можно импортировать в проекте:

import interact from '@interactjs/interactjs';

Это обеспечивает доступ ко всем методам библиотеки, включая draggable, resizable и gesturable.


Создание draggable-элемента

Draggable — базовая функциональность для перемещения элементов на странице.

Пример создания элемента, который можно перемещать:

<div id="drag-element" style="width: 100px; height: 100px; background-color: #4CAF50; position: absolute;"></div>
interact('#drag-element').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 — смещение за один шаг перемещения.
  • data-x и data-y позволяют хранить текущее положение элемента.
  • Свойство transform: translate() используется для плавного перемещения без влияния на поток документа.

Добавление ограничения движения

Interact.js позволяет ограничить перемещение элемента в пределах родителя или заданной области.

interact('#drag-element').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);
    }
  }
});

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

  • restriction: 'parent' ограничивает движение рамками родительского контейнера.
  • endOnly: true применяет ограничения только в конце перемещения, позволяя плавно двигать элемент в процессе.

Создание resizable-элемента

Resizable позволяет изменять размеры элементов динамически.

interact('#drag-element').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.modifiers.restrictSize({
      min: { width: 50, height: 50 },
      max: { width: 300, height: 300 }
    })
  ]
});

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

  • edges задаёт, с каких сторон элемент можно изменять.
  • event.rect содержит актуальные размеры элемента.
  • restrictEdges и restrictSize позволяют ограничивать размеры и положение при изменении.

Обработка событий взаимодействия

Interact.js предоставляет мощные события для всех типов взаимодействий: start, move, end.

interact('#drag-element').draggable({
  listeners: {
    start(event) {
      console.log('Начало перемещения', event);
    },
    move(event) {
      // движение элемента
    },
    end(event) {
      console.log('Перемещение завершено', event);
    }
  }
});

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

  • start срабатывает при начале действия (перетаскивания, изменения размера).
  • move вызывается каждый кадр перемещения.
  • end активируется при завершении взаимодействия.

Комбинирование draggable и resizable

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

interact('#drag-element')
  .draggable({
    listeners: { move: dragMoveListener }
  })
  .resizable({
    edges: { left: true, right: true, bottom: true, top: true },
    listeners: { move: resizeMoveListener }
  });

function dragMoveListener(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);
}

function resizeMoveListener(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);
}

Использование snap и grid

Interact.js позволяет “привязывать” элементы к сетке, что удобно для интерфейсов с упорядоченными блоками.

interact('#drag-element').draggable({
  modifiers: [
    interact.modifiers.snap({
      targets: [interact.snappers.grid({ x: 50, y: 50 })],
      range: Infinity,
      relativePoints: [{ x: 0, y: 0 }]
    })
  ],
  listeners: { move: dragMoveListener }
});

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

  • interact.snappers.grid({ x, y }) создаёт сетку с шагом x и y.
  • Элемент “прилипает” к ближайшей точке сетки при движении.

Интеграция с CSS и стилями

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

  • Цвета: target.style.backgroundColor = '#ff0000'
  • Прозрачность: target.style.opacity = 0.5
  • Тени и эффекты при drag: target.style.boxShadow = '0 5px 15px rgba(0,0,0,0.3)'

Это позволяет создавать визуально насыщенные и отзывчивые интерфейсы.


Оптимизация производительности

  • Использовать requestAnimationFrame для heavy операций.
  • Ограничивать количество одновременно draggable/resizable элементов.
  • Минимизировать пересчёт стилей внутри слушателей move.
  • Использовать will-change: transform в CSS для плавной анимации.

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