React Image Reordering Grid Drag and Drop (для ПК и мобильных устройств)
25 апреля 2023 г.Начиналось все очень просто: меня попросили сделать так, чтобы пользователи могли обмениваться фотографиями в галерее. Что меня удивило, когда я узнал, что в браузерах мобильных телефонов нет drag & сброс (DnD) встроенный? Когда я посмотрел исходники, мой проект был единственным, в котором использовалась DnD. И я почему-то решил, что моя работа похожа на ту, что уже была сделана. Но это было не так просто.
React-beautiful-dnd
Предыдущая реализация была для DnD по оси Y, и она плохо работала для сетки.
Но на тот момент, когда я это понял, фичу уже нужно было реализовать. И я решил сделать это просто, по примеру react-beautiful-dnd-grid. По сути, это просто разбиение одномерного массива на куски, а дальше работа продолжается, как и со многими одномерными массивами.
Краткое введение в react-beautiful-dnd
Прекрасный DND React состоит из нескольких базовых компонентов.
* Dropzone: это место, куда перетаскивается элемент; сам компонент реализован через шаблон рендеринга дочерних элементов. * Draggable — перетаскиваемый элемент; сам компонент реализован через шаблон рендеринга дочерних элементов. * DragContext: контекст для обработчиков (возможна обработка нескольких зон перетаскивания и т. д.)
Основное использование — DnD по оси X.
Моя реализация была просто расширением этого поведения, разделение изображений на фрагменты, затем каждый фрагмент представляет собой строку (которая является Dropzone), и каждое изображение можно перетаскивать. Когда я обрабатываю событие onDragEnd в DragContext, я просто сопоставляю индекс строки (фрагмента) и индекс в строке с индексом одномерного массива.:
const originalIndex = destinationChunkIndex * maxItems + indexInChunk + (sourceChunkIndex < destinationChunkIndex ? -1 : 0);
Все было реализовано, и фича уже пару недель была в поле зрения, но потом пришло время ревью дизайна, а мне говорят, что все фигня. Верните его обратно.
На самом деле основная проблема заключалась в том, что если со столбцами такое решение выглядит хорошо, то со строками есть небольшие проблемы. Например, то, что фотографии улетают с экрана и вообще нет ощущения, что так и должно быть
Если хотите, можете поиграть на моей игровой площадке. Возможно, такое решение подойдет для вашего случая. https://codesandbox.io/p/github/pivaszbs/image- переупорядочение-прекрасный-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
. Честно говоря, это просто элементы и стратегия сортировки (чтобы понимать, когда нужно переупорядочивать элементы на экране).useSortable
Hook — это абстракция, которая объединяет хуки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 я сделал небольшой пример с картинки.
Шаг 2
Тогда я сразу понял, что UX — это так себе история, и добавил ограничения активации.
Шаг 3
Однако это не сработало, и в Safari появилось контекстное меню.
Поэтому я добавил user-select: none
Шаг 4
Затем мне понадобился DragOverlay, чтобы пользователь понимал, где будет его изображение.
Шаг 5
Далее я решил, что стоит попытаться описать, как на примерах сделать компонент сортируемым, чтобы можно было повторно использовать абстракцию вместо примитивов. Было довольно сложно, но сейчас лучше, чем в примерах.
https://codesandbox.io/ p/sandbox/react-image-reordering-grid-mobile-ssnzd2?file=%2Fsrc%2FApp.tsx
Заключение
Я очень рад, что вы зашли так далеко со мной. Надеюсь, мне удалось сэкономить ваше время (это был не простой, но интересный способ). Я думаю, что будущее за такими библиотеками, как dnd-kit, с их небольшим размером, хорошим встряхиванием деревьев и настройкой. Я думаю, что такие библиотеки, как react-dnd и react-beautiful-dnd, уйдут в прошлое. Спасибо за ваше время!
Полезные ссылки
- https://dndkit.com/
- https://docs.dndkit.com/
- https://master--5fc05e08a4a65d0021ae0bf2.chromatic. com/?path=/story/presets-sortable-grid--basic-setup
- https://github.com/react-dnd/react-dnd
- https://github.com/atlassian/react-beautiful-dnd
- https://www.npmjs.com/package/mobile-drag-drop ли>
Все песочницы, шаг за шагом
- https://codesandbox.io/p/github/pivaszbs /image-reordering-beautiful-dnd/draft/gifted-voice
- https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-w0wlnh?file=%2Fsrc%2FApp.tsx
- https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-1thxdp?file=%2Fsrc%2FApp.tsx
- https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-dwi8cb?file=%2Fsrc%2FImage.tsx
- https://codesandbox. io/p/sandbox/react-image-reordering-grid-mobile-forked-revjso?file=%2Fsrc%2FApp.tsx
- https://codesandbox.io/ p/sandbox/react-image-reordering-grid-mobile-ssnzd2?file=%2Fsrc%2FApp.tsx
Оригинал