Компоненты/Бегущая строка

Бегущая строка

31 января 2025

Плавная зацикленная строка, которая горизонтально везёт содержимое

Установка

npx astra-rn add marquee
pnpm dlx astra-rn add marquee
yarn dlx astra-rn add marquee
bunx --bun astra-rn add marquee

Файлы

index.tsx
НазадСтена логотиповДалееЛента отзывов и логотипов

Вручную

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

npm install react-native-reanimated
pnpm add react-native-reanimated
yarn add react-native-reanimated
bun add react-native-reanimated

Скопируйте эти файлы в src/shared/components/base/marquee/:

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

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

import { View, StyleSheet, Text, Dimensions } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import Marquee from "@/shared/components/base/marquee";
import { useFonts } from "expo-font";
import { Showcase, useCustomize } from "~/showcase";
import { LinearGradient } from "expo-linear-gradient";

const WIDTH = Dimensions.get("window").width;

const CUSTOMIZE = [
  { key: "text", label: "Текст", type: "text", default: "Astra", maxLength: 32 },
  { key: "separator", label: "Разделитель", type: "text", default: "⋆ ✦ ⋆", maxLength: 12 },
  { key: "color", label: "Цвет текста", type: "color", default: "#ffffff" },
  { key: "fontSize", label: "Размер шрифта", type: "slider", min: 14, max: 72, step: 1, unit: "px", default: 35 },
  { key: "speed", label: "Скорость", type: "slider", min: 0, max: 300, step: 5, default: 50 },
  { key: "spacing", label: "Интервал", type: "slider", min: 0, max: 80, step: 1, unit: "px", default: 20 },
  { key: "reverse", label: "Обратно", type: "toggle", default: false },
  { key: "fade", label: "Затухание краёв", type: "toggle", default: true },
  { key: "holdToSpeedUp", label: "Ускорять удержанием", type: "toggle", default: false },
] as const;

export default function App() {
  const [fontLoaded] = useFonts({
    SfProRounded: require("@/assets/fonts/sf-pro-rounded.ttf"),
    HelveticaNowDisplay: require("@/assets/fonts/HelveticaNowDisplayMedium.ttf"),
  });
  const custom = useCustomize(CUSTOMIZE);
  const textStyle = [
    styles.text,
    {
      fontFamily: "SfProRounded",
      color: custom.color,
      fontSize: custom.fontSize,
    },
  ];

  return (
    <Showcase>
      <GestureHandlerRootView style={styles.container}>
        <StatusBar style="light" />
        <View style={styles.marqueeContainer}>
          {fontLoaded ? (
          <Marquee
            key={`${custom.text}|${custom.separator}|${custom.fontSize}`}
            speed={custom.speed}
            spacing={custom.spacing}
            reverse={custom.reverse}
            holdToSpeedUp={custom.holdToSpeedUp}
          >
            <Text style={textStyle}>{custom.separator}</Text>

            <View style={styles.divider} />

            <Text style={textStyle}>{custom.text}</Text>
          </Marquee>
          ) : null}

          {custom.fade ? (
          <>
          <LinearGradient
            pointerEvents="none"
            colors={["#0a0a0a", "transparent"]}
            start={{ x: 0, y: 0 }}
            end={{ x: 1, y: 0 }}
            style={styles.leftGradient}
          />

          <LinearGradient
            pointerEvents="none"
            colors={["transparent", "#0a0a0a"]}
            start={{ x: 0, y: 0 }}
            end={{ x: 1, y: 0 }}
            style={styles.rightGradient}
          />
          </>
          ) : null}
        </View>
      </GestureHandlerRootView>
    </Showcase>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#0a0a0a",
    alignItems: "center",
  },

  marqueeContainer: {
    width: WIDTH,
    alignItems: "center",
    flex: 1,
    justifyContent: "center",
    overflow: "hidden",
  },

  leftGradient: {
    position: "absolute",
    left: 0,
    top: 0,
    bottom: 0,
    width: 100,
    zIndex: 2,
  },

  rightGradient: {
    position: "absolute",
    right: 0,
    top: 0,
    bottom: 0,
    width: 100,
    zIndex: 2,
  },

  divider: {
    width: 20,
  },

  text: {
    fontSize: 35,
    color: "#fff",
  },
});

Пропсы

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

Тип React.ReactNode

speed?

Тип number

spacing?

Тип number

reverse?

Тип boolean

pauseOnPress?

Тип boolean

holdToSpeedUp?

Тип boolean

speedUpMultiplier?

Тип number