Carousel
Набор компонентов для создания списков с прокруткой (галерей).
Состав
При сборке карусели используйте структуру, в которой корневым элементом
является Carousel
со вложенными в него CarouselItem
или CarouselCol
.
При необходимости отображения элементов карусели в сетке, оборачивайте карусель в CarouselGridWrapper
.
Carousel
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
- В компоненте
Carousel
укажите свойствоscrollSnapType
:
import React from 'react';
import { Carousel } from '@salutejs/plasma-ui';
export const MyGallery = () = (
<Carousel scrollSnapType="mandatory">
// Элементы карусели помещаются здесь
</Carousel>
);
- Также укажите свойство
scrollSnapAlign
для элемента карусели:
import React from 'react';
import { CarouselItem } from '@salutejs/plasma-ui';
export const MyGalleryItem = ({ children }) => (
<CarouselItem scrollSnapAlign="center">{children}</CarouselItem>
);
Определение центрального элемента
Карусель может определять активный элемент при прокрутке.
Для этого укажите свойства detectActive
, detectThreshold
и обработчик onIndexChange
:
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: number | void |
stylingResetCallback | Обработчик для элементов вне viewport . Элемент невидим, стилизация сбрасывается. | itemEl: HTMLElement | void |
Для обозначения позиции элемента внутри viewport
, карусель использует значение slot
:
0
равен центральному элементу;-1
и1
первый слева и справа от центрального;-2
и2
и т.д., соответственно, для второго и далее.
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
) активного элемента.
Пример использования CarouselLite
Карусель с "виртуализированным" списком элементов
Если ваша карусель содержит большое количество элементов, рекомендуем использовать "виртуализацию". Этот подход позволяет рендерить только то количество элементов, которое помещается во вьюпорт. Это позволит значительно сократить время на первый и последующие рендеры карусели.
Доступность
В элемент карусели добавьте атрибут aria-label
,
со значением, обозначающим текущую позицию в списке:
<Carousel>
{items.map((item, i) => <CarouselItem aria-label={`${i + 1} из ${items.length}`} />)}
</Carousel>