Carousel

Набор компонентов для создания списков с прокруткой (галерей).

Состав​

При сборке карусели используйте структуру, в которой корневым элементом является Carousel со вложенными в него CarouselItem или CarouselCol. При необходимости отображения элементов карусели в сетке, оборачивайте карусель в CarouselGridWrapper.

CarouselLite​

CarouselVirtual​

Рекомендуется использовать вместе с хуком, который возвращает "виртуализированный" список элементов.

import { useVirtual } from '@salutejs/use-virtual';

Многие фичи обычной Carousel поддерживаются внутри данного хука:

  • useVirtual возвращает активный элемент ( = detectActive)
  • onIndexChange, onDetectActiveItem легко реализовать по месту использования, учитывая доступ к активному элементу из хука
  • scrollAlign надо передавать в useVirtual
  • paddingStart, paddingEnd также передаются в useVirtual (px)

Некоторые фичи обычной Carousel не поддерживаются:

  • animatedScrollByIndex
  • scrollSnapType
  • throttleMs
  • debounceMs
  • scaleCallback
  • scaleResetCallback

CarouselGridWrapper​

CarouselItem​

CarouselItemVirtual​

CarouselCol​

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

CSS Scroll Snap​

  1. В компоненте Carousel укажите свойство scrollSnapType:
MyGallery.tsx
import React from 'react';
import { Carousel } from '@salutejs/plasma-ui';

export const MyGallery = () = (
<Carousel scrollSnapType="mandatory">
// Элементы карусели помещаются здесь
</Carousel>
);
  1. Также укажите свойство scrollSnapAlign для элемента карусели:
MyGallery.tsx
import React from 'react';
import { CarouselItem } from '@salutejs/plasma-ui';

export const MyGalleryItem = ({ children }) => (
<CarouselItem scrollSnapAlign="center">{children}</CarouselItem>
);

Определение центрального элемента​

Карусель может определять активный элемент при прокрутке. Для этого укажите свойства detectActive, detectThreshold и обработчик onIndexChange:

MyGallery.tsx
import React from 'react';
import { Carousel } from '@salutejs/plasma-ui';

export const MyGallery = () = (
<Carousel detectActive detectThreshold={0.5} onIndexChange={(index) => console.log(index)}>
// Элементы карусели помещаются здесь
</Carousel>
);

Стилизация центрального элемента​

Элементы видимой части (viewport) можно стилизовать, например, увеличивать или менять *прозрачность.

В момент прокрутки карусели (с помощью колесика мыши, стрелок пульта или касанием) с определенной периодичностью вызывается обработчик скролла, который на основании положения элемента относительно viewport (внутренние границы карусели) вызывает тот или иной коллбек:

НазваниеОписаниеАргументыВозвращаемое значение
stylingCallbackОбработчик для элементов внутри viewport. Коллбек вызывается для видимого элемента, к нему применяется необходимая стилизация.itemEl: HTMLElement, slot: numbervoid
stylingResetCallbackОбработчик для элементов вне viewport. Элемент невидим, стилизация сбрасывается.itemEl: HTMLElementvoid

Для обозначения позиции элемента внутри viewport, карусель использует значение slot:

  • 0 равен центральному элементу;
  • -1 и 1 первый слева и справа от центрального;
  • -2 и 2 и т.д., соответственно, для второго и далее.
MyGallery.tsx
import React from 'react';
import { Carousel } from '@salutejs/plasma-ui';

/**
* Функция увеличения центрального элемента.
* Предположим, что у нас 5 элементов в внутри `viewport`.
* Тогда ряд slots будет таким: -2 -1 0 1 2.
* Центральный элемент примет opacity = 1, боковые - opacity = 0.5, а крайние слева и справа - opacity = 0
*/
const stylingCallback = (itemEl: HTMLDivElement, slot: number) => {
itemEl.style.opacity = `${1 - Math.abs(slot) / 2}`;
};

/**
* Функция сброса стилей элементов вне `viewport`.
*/
const stylingResetCallback = (itemEl: HTMLDivElement) => {
itemEl.style.opacity = '';
};

export const MyGallery = () = (
<Carousel stylingCallback={stylingCallback} stylingResetCallback={stylingResetCallback}>
// Элементы карусели помещаются здесь
</Carousel>
);
  • В данном примере используются Grid и CSS Scroll Snap.
  • В корне приложения необходимо разместить DeviceThemeProvider.
  • В качестве основного блока разметки контейнер (Container), а колонки (Col) помещаются в строки (Row).
  • Карусель поддерживает определение (detectActive) активного элемента.
Live Editor

Result

Пример использования CarouselLite​

Live Editor

Result

Карусель с "виртуализированным" списком элементов​

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

Live Editor

Result

Доступность​

В элемент карусели добавьте атрибут aria-label, со значением, обозначающим текущую позицию в списке:

<Carousel>
{items.map((item, i) => <CarouselItem aria-label={`${i + 1} из ${items.length}`} />)}
</Carousel>