Компоненты/Текст под маской

Текст под маской

31 января 2025

Выбор чипов, где элемент раскрывается при нажатии

Установка

npx astra-rn add animated-masked-text
pnpm dlx astra-rn add animated-masked-text
yarn dlx astra-rn add animated-masked-text
bunx --bun astra-rn add animated-masked-text

Файлы

AnimatedMaskedText.tsx
НазадЖивое поле вводаДалееАнимированный список выбора

Вручную

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

npm install @react-native-masked-view/masked-view expo-linear-gradient
pnpm add @react-native-masked-view/masked-view expo-linear-gradient
yarn add @react-native-masked-view/masked-view expo-linear-gradient
bun add @react-native-masked-view/masked-view expo-linear-gradient

Скопируйте эти файлы в src/shared/components/molecules/animated-masked-text/:

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

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

import { View, Text, StyleSheet } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import { useFonts } from "expo-font";
import { SymbolView } from "expo-symbols";
import { useMemo, useState } from "react";
import AnimatedMaskedText from "@/shared/components/molecules/animated-masked-text/AnimatedMaskedText";
import { hexToRgb, Showcase, useCustomize } from "~/showcase";

const SHIMMER_DEFAULT = "#ffffff";

const CUSTOMIZE = [
  { key: "text", label: "Текст", type: "text", default: "Astra", maxLength: 16 },
  { key: "fontSize", label: "Размер", type: "slider", min: 32, max: 120, step: 1, unit: "px", default: 80 },
  { key: "fontWeight", label: "Насыщенность", type: "select", options: ["100", "200", "400", "600", "800"], default: "200" },
  { key: "speed", label: "Скорость", type: "slider", min: 0.2, max: 4, step: 0.1, default: 1.3 },
  { key: "waveLength", label: "Ширина блика", type: "slider", min: 0.2, max: 3, step: 0.1, default: 1 },
  { key: "baseColor", label: "Цвет текста", type: "color", default: "#2a2a2a" },
  { key: "shimmer", label: "Цвет блика", type: "color", default: SHIMMER_DEFAULT },
  { key: "background", label: "Фон", type: "color", default: "#0a0a0a" },
] as const;

export default function App() {
  const custom = useCustomize(CUSTOMIZE);
  const shimmerHex = custom.shimmer;

  const shimmerColors = useMemo(() => {
    if (shimmerHex === SHIMMER_DEFAULT) return undefined;
    const { r, g, b } = hexToRgb(shimmerHex);
    const rgba = (alpha: number) =>
      `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${alpha})`;
    return ["transparent", rgba(0.5), rgba(1), rgba(0.2), "transparent"];
  }, [shimmerHex]);

  return (
    <Showcase>
      <View style={[styles.container, { backgroundColor: custom.background }]}>
        <StatusBar style="light" />

        <View style={styles.content}>
          <AnimatedMaskedText
            key={`${custom.text}-${custom.fontSize}-${custom.fontWeight}`}
            style={{
              fontSize: custom.fontSize,
              fontWeight: custom.fontWeight as "200",
            }}
            speed={custom.speed}
            textWaveLength={custom.waveLength}
            baseTextColor={custom.baseColor}
            colors={shimmerColors}
          >
            {custom.text}
          </AnimatedMaskedText>
        </View>
      </View>
    </Showcase>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#0a0a0a",
  },
  content: {
    justifyContent: "center",
    alignItems: "center",
    flex: 1,
    gap: 24,
  },
  title: {
    fontSize: 34,
    fontWeight: "700",
    color: "#fff",
  },
});

Пропсы

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

Тип string

speed?

Тип number

textWaveLength?

Тип number

colors?

@type {string[]} @memberof AnimatedMaskedTextProps @description The first color in the array is always going to be "transparent."

Тип string[]

baseTextColor?

Тип string

style?

Тип StyleProp<TextStyle>