Компоненты/Бесконечный холст

Бесконечный холст

Pro
28 сентября 2026

Бесконечное поле карточек, которое само плывёт, бесшовно повторяется по обеим осям и бросается пальцем в любую сторону.

Установка

import { useEffect, useMemo } from "react";
import Animated, { useSharedValue } from "react-native-reanimated";
import { StyleSheet, View } from "react-native";

Установка через CLIPro

Команда станет доступна после оформления Pro.

Оформить ProВойти

Файлы

index.tsx
НазадБесконечное менюДалееЛучи интеграций

Поле карточек с фотографиями, у которого нет краёв: оно медленно дрейфует само и бесшовно повторяется по горизонтали и вертикали. Холст можно схватить пальцем или мышью и бросить — он полетит по инерции и плавно затормозит, а затем снова продолжит дрейф. Колонки смещены в шахматном порядке, края растворяются в цвете fadeColor. Касание карточки без перетаскивания вызывает её onPress.

Позиция считается на UI-потоке Reanimated, жест — через Gesture Handler, поэтому React не перерисовывается на каждом кадре. При включённом «Уменьшении движения» дрейф выключается, а бросок остаётся. Работает на iOS, Android и в вебе.

Вручную

Поставьте зависимости:

npm install expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets
pnpm add expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets
yarn add expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets
bun add expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets

Скопируйте эти файлы в src/shared/components/organisms/infinity-canvas/:

index.tsx
import { useEffect, useMemo } from "react";
import Animated, { useSharedValue } from "react-native-reanimated";
import { StyleSheet, View } from "react-native";
// Полный исходник открывается с подпиской Pro
export interface InfinityCanvasProps {
speed?: number;
intensity?: number;
palette?: "aurora" | "mono";
interactive?: boolean;
}
export function InfinityCanvas({
speed = 1,
intensity = 0.6,
interactive = true,
}: InfinityCanvasProps) {
const progress = useSharedValue(0);
const frame = useMemo(() => createFrame(speed), [speed]);
useEffect(() => {
// …

Код доступен по подпискеPro

Исходник «Бесконечный холст» открывается с подпиской Pro. Уже оформили? Войдите в аккаунт.

Оформить ProВойти

Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.

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

usage.tsx
import { useEffect, useMemo } from "react";
import Animated, { useSharedValue } from "react-native-reanimated";
import { StyleSheet, View } from "react-native";
// Полный исходник открывается с подпиской Pro
export interface InfinityCanvasProps {
speed?: number;
intensity?: number;
palette?: "aurora" | "mono";
interactive?: boolean;
}
export function InfinityCanvas({
speed = 1,
intensity = 0.6,
interactive = true,
}: InfinityCanvasProps) {
const progress = useSharedValue(0);
const frame = useMemo(() => createFrame(speed), [speed]);
useEffect(() => {
// …

Код доступен по подпискеPro

Исходник «Бесконечный холст» открывается с подпиской Pro. Уже оформили? Войдите в аккаунт.

Оформить ProВойти

Передайте items с фотографиями; высоту задаёт height, а цвет растворения краёв — fadeColor.

Пропсы

Пропс
Описание
items

Тип readonly InfinityCanvasItem[]

columns?

Тип number

cardWidth?

Тип number

gap?

Тип number

drift?

Тип { readonly x: number; readonly y: number }

height?

Тип number

fadeColor?

Тип string

style?

Тип StyleProp<ViewStyle>