React Image Reordering Grid Drag and Drop (для ПК и мобильных устройств)

React Image Reordering Grid Drag and Drop (для ПК и мобильных устройств)

25 апреля 2023 г.

Начиналось все очень просто: меня попросили сделать так, чтобы пользователи могли обмениваться фотографиями в галерее. Что меня удивило, когда я узнал, что в браузерах мобильных телефонов нет drag & сброс (DnD) встроенный? Когда я посмотрел исходники, мой проект был единственным, в котором использовалась DnD. И я почему-то решил, что моя работа похожа на ту, что уже была сделана. Но это было не так просто.

React-beautiful-dnd

Предыдущая реализация была для DnD по оси Y, и она плохо работала для сетки.

Y axis DnD

Но на тот момент, когда я это понял, фичу уже нужно было реализовать. И я решил сделать это просто, по примеру react-beautiful-dnd-grid. По сути, это просто разбиение одномерного массива на куски, а дальше работа продолжается, как и со многими одномерными массивами.

Краткое введение в react-beautiful-dnd

Прекрасный DND React состоит из нескольких базовых компонентов.

* Dropzone: это место, куда перетаскивается элемент; сам компонент реализован через шаблон рендеринга дочерних элементов. * Draggable — перетаскиваемый элемент; сам компонент реализован через шаблон рендеринга дочерних элементов. * DragContext: контекст для обработчиков (возможна обработка нескольких зон перетаскивания и т. д.)

Основное использование — DnD по оси X.

One-dimensional X axis DnD

Моя реализация была просто расширением этого поведения, разделение изображений на фрагменты, затем каждый фрагмент представляет собой строку (которая является Dropzone), и каждое изображение можно перетаскивать. Когда я обрабатываю событие onDragEnd в DragContext, я просто сопоставляю индекс строки (фрагмента) и индекс в строке с индексом одномерного массива.:

const originalIndex = destinationChunkIndex * maxItems + indexInChunk + (sourceChunkIndex < destinationChunkIndex ? -1 : 0);

N-X axis rows DnD

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

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

React-beautiful-dnd n-rows trouble

Если хотите, можете поиграть на моей игровой площадке. Возможно, такое решение подойдет для вашего случая. https://codesandbox.io/p/github/pivaszbs/image- переупорядочение-прекрасный-dnd/черновик/одаренный-голос

Поэтому я понимаю, что мне нужна реальная реализация сетки, которая выглядит так, поэтому я решил продолжить исследования.

Real grid DnD

Реализация полифилла

Далее я реализовал эту функцию на десктопе, и там все было очень просто из-за поддержки браузером DnD, поэтому я подумал, а почему бы не использовать полифилл?

https://www.npmjs.com/package/mobile-drag-drop?embedable =правда

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

Набор DnD

Казалось бы, что мое существование напрасно и что я никогда не добьюсь успеха. Но настал момент истины, и я увидел уведомление о замечательной библиотеке на одном из каналов в Telegram.

https://dndkit.com/?embedable=true

Я обрадовался, глядя на размер библиотеки и на то, как красиво реализованы примеры в документации. Я сразу пошел смотреть примеры на площадку. Помимо поддержки DnD для сеток, библиотека также поддерживает специальные возможности и очень настраиваема.

Краткое введение в DnD-kit

Я не хочу наблюдать за всем, только то, что необходимо для понимания моего решения этой проблемы. Я рассмотрю SortableContext, useSortable, DragOverlay и useSensors, но это абстракция над примитивами. DndContext, useDroppable, useDraggable (знакомые слова: он выглядит так же, как react-beautiful-dnd, но использует хуки вместо шаблона рендеринга детей). Если вы хотите узнать о примитивах, просмотрите документацию

  • SortableContextпредоставляет информацию через контекст, используемый хуком useSortable. Честно говоря, это просто элементы и стратегия сортировки (чтобы понимать, когда нужно переупорядочивать элементы на экране).
  • useSortableHook — это абстракция, которая объединяет хуки useDroppable и useDraggable. В моем случае я могу отбрасывать все в своем контейнере изображений, и это должно быть переупорядочено. Итак, здесь каждый прямоугольник — это место, куда мы можем поместить изображение.
  • DragOverlay — отличная вещь для UX и анимации. В моем случае это показывает место, куда я перетащу изображение.
  • useSensorsхук для работы с абстракцией для обнаружения различных методов ввода, чтобы инициировать операции перетаскивания, реагировать на движение и завершать или отменять операцию. По сути, это помощник для обработки событий (касание, клавиатура или мышь).

Реализация DnD в реальной сети

Этот пример идеально подошёл мне, поэтому я мог посмотреть исходники.

https://codesandbox.io/p/github/pivaszbs /image-reordering-beautiful-dnd/draft/gifted-voice

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

Шаг 1

В соответствии с документами https://docs.dndkit.com/presets/sortable я сделал небольшой пример с картинки.

https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-w0wlnh?file=%2Fsrc%2FApp.tsx

Шаг 2

Тогда я сразу понял, что UX — это так себе история, и добавил ограничения активации.

https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-w0wlnh?file=%2Fsrc%2FApp.tsx

Шаг 3

Однако это не сработало, и в Safari появилось контекстное меню.

Поэтому я добавил user-select: none

user-select trouble

https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-dwi8cb?file=%2Fsrc%2FImage.tsx

Шаг 4

Затем мне понадобился DragOverlay, чтобы пользователь понимал, где будет его изображение.

https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-revjso?file=%2Fsrc%2FApp.tsx

Шаг 5

Далее я решил, что стоит попытаться описать, как на примерах сделать компонент сортируемым, чтобы можно было повторно использовать абстракцию вместо примитивов. Было довольно сложно, но сейчас лучше, чем в примерах.

https://codesandbox.io/ p/sandbox/react-image-reordering-grid-mobile-ssnzd2?file=%2Fsrc%2FApp.tsx

Заключение

Я очень рад, что вы зашли так далеко со мной. Надеюсь, мне удалось сэкономить ваше время (это был не простой, но интересный способ). Я думаю, что будущее за такими библиотеками, как dnd-kit, с их небольшим размером, хорошим встряхиванием деревьев и настройкой. Я думаю, что такие библиотеки, как react-dnd и react-beautiful-dnd, уйдут в прошлое. Спасибо за ваше время!

Полезные ссылки

  1. https://dndkit.com/
  2. https://docs.dndkit.com/
  3. https://master--5fc05e08a4a65d0021ae0bf2.chromatic. com/?path=/story/presets-sortable-grid--basic-setup
  4. https://github.com/react-dnd/react-dnd
  5. https://github.com/atlassian/react-beautiful-dnd
  6. https://www.npmjs.com/package/mobile-drag-drop

Все песочницы, шаг за шагом

  1. https://codesandbox.io/p/github/pivaszbs /image-reordering-beautiful-dnd/draft/gifted-voice
  2. https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-w0wlnh?file=%2Fsrc%2FApp.tsx
  3. https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-1thxdp?file=%2Fsrc%2FApp.tsx
  4. https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-dwi8cb?file=%2Fsrc%2FImage.tsx
  5. https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-revjso?file=%2Fsrc%2FApp.tsx
  6. https://codesandbox.io/ p/sandbox/react-image-reordering-grid-mobile-ssnzd2?file=%2Fsrc%2FApp.tsx


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE