Эта проблема

При создании приложения OneJournal я хотел обеспечить функциональность смахивания для перехода между записями журнала. Однако это создало проблему, потому что список записей журнала бесконечен. В то время я использовал Framer Motion для других анимаций и решил создать карусель с этим вместо использования другой библиотеки, которая потенциально увеличила бы размер пакета, а не реализовала ее самостоятельно.

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

  1. Определение интерфейса для нашей карусели
  2. Размещение элементов на экране
  3. Добавление поведения перетаскивания.

Если вас интересует только конечный результат, вы можете прокрутить страницу вниз и найти ссылку на Codesandbox и Github.

VirtualizedPage

Интерфейс

Нам нужно будет динамически отображать дочерние элементы на основе текущего видимого индекса, а также страницы слева и справа от этого индекса. Для этого мы можем использовать свойства рендеринга и передавать индекс, который мы хотим отображать. Это очень похоже на то, как это делает React-window.

Теперь, когда мы знаем, как будет выглядеть интерфейс, мы можем начать думать о создании компонентов. Мы разделим проблему на два разных компонента.
Один будет отвечать за организацию всего, а другой - за отрисовку дочерних страниц.

Размещение различных предметов в карусели

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

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

style={{
   ...pageStyle,
   left: `${index * 100}%`,
   right: `${index * 100}%`
}}

Добавить поведение перетаскивания

Чтобы добавить поведение перетаскивания, нам нужно будет синхронизировать все элементы друг с другом. К счастью, framer-motion предоставляет ловушку для этого, nameduseMotionValue.

Теперь у нас есть кое-что, куда вы можете перетаскивать элементы, но у нас все еще есть несколько проблем, которые нужно решить.

  1. Карусель отображает только элементы с index-1, 0, 1 и никогда не обновляется.
  2. Карусель не привязывается к элементу при отпускании

Чтобы выполнить оба этих требования, нам нужно будет обновить текущий индекс и оживить x до правильного значения. Для простоты мы будем обновлять индекс, когда пользователь перетаскивает элемент более чем на 1/4 ширины контейнера.

Подведение итогов

Используя примитивы, предоставляемые движением кадра, мы можем легко создать нашу собственную версию многоразовой карусели. Этот компонент используется для обзора журнала, навигации по календарю и галереи изображений внутри приложения.

Вы можете найти окончательный результат здесь:
https://codesandbox.io/s/github/koenvg/infinite-carousel-with-framer-motion
https://github.com/ koenvg / бесконечная карусель с движением кадра