Компоненты/Тягучий текст

Тягучий текст

31 января 2025

Текст перетекает между словами через тягучее размытие

Установка

npx astra-rn add gooey-text
pnpm dlx astra-rn add gooey-text
yarn dlx astra-rn add gooey-text
bunx --bun astra-rn add gooey-text

Файлы

index.tsx
НазадТекст с фейдомДалееВолна градиента

Вручную

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

npm install @shopify/react-native-skia react-native-reanimated
pnpm add @shopify/react-native-skia react-native-reanimated
yarn add @shopify/react-native-skia react-native-reanimated
bun add @shopify/react-native-skia react-native-reanimated

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

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

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

import { View, StyleSheet } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import GooeyText from "@/shared/components/molecules/gooey-text";
import { useMemo } from "react";
import { Showcase, useCustomize } from "~/showcase";

const CUSTOMIZE = [
  { key: "word1", label: "Слово 1", type: "text", default: "ASTRA", maxLength: 12 },
  { key: "word2", label: "Слово 2", type: "text", default: "IS", maxLength: 12 },
  { key: "word3", label: "Слово 3", type: "text", default: "AWESOME!", maxLength: 12 },
  { key: "color", label: "Цвет текста", type: "color", default: "#ffffff" },
  { key: "fontSize", label: "Размер шрифта", type: "slider", min: 20, max: 80, step: 1, unit: "px", default: 50 },
  { key: "morphTime", label: "Перетекание", type: "slider", min: 0.2, max: 3, step: 0.1, unit: "s", default: 1 },
  { key: "cooldownTime", label: "Пауза", type: "slider", min: 0, max: 2, step: 0.05, unit: "s", default: 0.25 },
] as const;

export default function App() {
  const custom = useCustomize(CUSTOMIZE);
  const { word1, word2, word3 } = custom;
  const texts = useMemo(() => [word1, word2, word3], [word1, word2, word3]);

  return (
    <Showcase>
      <GestureHandlerRootView style={styles.container}>
        <StatusBar style="light" />

        <View style={styles.content}>
          <GooeyText
            texts={texts}
            color={custom.color}
            fontSize={custom.fontSize}
            morphTime={custom.morphTime}
            cooldownTime={custom.cooldownTime}
          />
        </View>
      </GestureHandlerRootView>
    </Showcase>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#0a0a0a",
    justifyContent: "center",
    alignItems: "center",
  },
  content: {},
  title: {
    fontSize: 28,
    fontWeight: "700",
    color: "#fff",
  },
  subtitle: {
    fontSize: 15,
    color: "#555",
  },
  card: {
    backgroundColor: "#141414",
    borderRadius: 16,
    overflow: "hidden",
    marginTop: 20,
  },
  triggerContent: {
    padding: 16,
  },
  triggerLeft: {
    flexDirection: "row",
    alignItems: "center",
    gap: 12,
  },
  triggerText: {
    fontSize: 16,
    fontWeight: "500",
    color: "#fff",
  },
  item: {
    flexDirection: "row",
    alignItems: "center",
    gap: 12,
    padding: 14,
    backgroundColor: "#1a1a1a",
    borderRadius: 12,
    marginBottom: 6,
  },
  itemText: {
    fontSize: 15,
    color: "#fff",
  },
  destructiveText: {
    color: "#ff453a",
  },
});

Пропсы

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

Тип string[]

morphTime?

Тип number

cooldownTime?

Тип number

style?

Тип StyleProp<ViewStyle>

fontSize?

Тип number

color?

Тип string

fontSource?

Тип number | string

fontFamily?

Тип string

fontWeight?

Тип FontWeight

width?

Тип number

height?

Тип number

IGooeyTextItem

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

Тип string

index

Тип number

totalTexts

Тип number

masterClock

Тип SharedValue<number>

cooldownFraction

Тип number

font

Тип SkFont

color

Тип string

x

Тип number

y

Тип number