Drag and drop файлов

Interact.js — это мощная библиотека для реализации интерактивных элементов на веб-странице, включая drag and drop, ресайзинг и мульти-тач жесты. Для drag and drop она предоставляет удобный и гибкий API, позволяющий легко контролировать перетаскиваемые элементы и области их назначения.


Настройка перетаскиваемых элементов

Чтобы сделать элемент перетаскиваемым, используется метод interact(target).draggable(options). Основные параметры options:

  • inertia — включает эффект инерции после отпускания элемента.
  • modifiers — массив модификаторов для ограничения перемещения.
  • listeners — события жизненного цикла drag (start, move, end).

Пример базовой конфигурации:

interact('.draggable')
  .draggable({
    inertia: true,
    modifiers: [
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    listeners: {
      start (event) {
        console.log('Начало перетаскивания', event.target);
      },
      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);
      },
      end (event) {
        console.log('Перетаскивание завершено');
      }
    }
  });

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

  • Использование data-x и data-y позволяет хранить текущие координаты.
  • Модификаторы restrictRect ограничивают перемещение элементом внутри контейнера.

Настройка областей для дропа

Interact.js позволяет назначать dropzone для перетаскиваемых элементов через interact(target).dropzone(options). Основные опции:

  • accept — CSS-селектор или функция для фильтрации допустимых элементов.
  • overlap — процент пересечения, необходимый для успешного дропа.
  • ondrop / ondragenter / ondragleave — события, управляемые библиотекой.

Пример создания dropzone:

interact('.dropzone').dropzone({
  accept: '.draggable',
  overlap: 0.5,
  ondropactivate(event) {
    event.target.classList.add('drop-active');
  },
  ondragenter(event) {
    const draggableElement = event.relatedTarget;
    event.target.classList.add('drop-target');
    draggableElement.classList.add('can-drop');
  },
  ondragleave(event) {
    event.target.classList.remove('drop-target');
    event.relatedTarget.classList.remove('can-drop');
  },
  ondrop(event) {
    console.log('Элемент успешно сброшен', event.relatedTarget);
  },
  ondropdeactivate(event) {
    event.target.classList.remove('drop-active');
    event.target.classList.remove('drop-target');
  }
});

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

  • ondropactivate и ondropdeactivate полезны для визуальной индикации активности зоны.
  • overlap регулирует чувствительность — чем выше значение, тем больше пересечения требуется для срабатывания дропа.

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

Модификаторы позволяют гибко управлять поведением draggable-элементов:

  1. RestrictRect — ограничение по прямоугольнику.
  2. Snap — привязка к сетке или конкретным точкам.
  3. RestrictEdges — запрещает выход за пределы определенной области.

Пример привязки к сетке:

interact('.draggable')
  .draggable({
    modifiers: [
      interact.modifiers.snap({
        targets: [
          interact.createSnapGrid({ x: 50, y: 50 })
        ],
        range: Infinity,
        relativePoints: [{ x: 0, y: 0 }]
      })
    ]
  });

Перетаскивание файлов

Для drag and drop файлов необходимо сочетать Interact.js с нативным API File. Основная идея:

  1. Создать dropzone для элементов типа .file-dropzone.
  2. На событии ondrop получать список файлов через event.relatedTarget.files или через стандартное DataTransfer событие drop.

Пример обработки файлов:

const dropArea = document.querySelector('.file-dropzone');

interact(dropArea).dropzone({
  accept: '*',
  ondrop(event) {
    const dt = event.originalEvent.dataTransfer;
    const files = dt.files;
    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      console.log(`Файл: ${file.name}, размер: ${file.size} байт`);
    }
  }
});

Важные моменты:

  • dataTransfer.files содержит массив File объектов.
  • Для работы с drag and drop файлов важно предотвратить стандартное поведение браузера (event.preventDefault() в dragover).

Комбинирование drag и drop с другими взаимодействиями

Interact.js позволяет комбинировать drag, resize, и gestures в одном элементе:

interact('.interactive')
  .draggable({ /* drag options */ })
  .resizable({
    edges: { left: true, right: true, bottom: true, top: true },
    listeners: {
      move(event) {
        let { x, y } = event.target.dataset;
        x = parseFloat(x) || 0;
        y = parseFloat(y) || 0;

        Object.assign(event.target.style, {
          width: `${event.rect.width}px`,
          height: `${event.rect.height}px`,
          transform: `translate(${x}px, ${y}px)`
        });
      }
    }
  });

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


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

Для плавного drag and drop рекомендуется:

  • Использовать CSS transform вместо top/left.
  • Ограничивать количество обработчиков в move событии.
  • Применять requestAnimationFrame при сложной визуализации.
  • Использовать inertia только для больших объектов или сложных интерфейсов.

События жизненного цикла drag and drop

Interact.js предоставляет несколько ключевых событий:

  1. dragstart — начало перетаскивания.
  2. dragmove — движение элемента.
  3. dragend — завершение перетаскивания.
  4. dropactivate / dropdeactivate — активация/деактивация dropzone.
  5. dragenter / dragleave — элемент вошел или покинул dropzone.
  6. drop — успешный сброс элемента.

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


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

  • Для сложных интерфейсов с несколькими draggable элементами и dropzone лучше использовать динамическое создание селекторов и фильтрацию через accept.
  • Модификаторы помогают контролировать границы и поведение, что предотвращает пересечение элементов или выход за пределы контейнера.
  • Интеграция с File API позволяет реализовать полноценный drag and drop файлов без сторонних плагинов.

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