Поставьте зависимости:
npm install react-native-reanimated react-native-svgpnpm add react-native-reanimated react-native-svgyarn add react-native-reanimated react-native-svgbun add react-native-reanimated react-native-svgСкопируйте эти файлы в src/shared/components/organisms/circular-progress/:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет 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 { useEffect } from "react";
import { useSharedValue, withTiming, Easing } from "react-native-reanimated";
import { CircularProgress } from "@/shared/components/organisms/circular-progress";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";
const FILL_EASING = Easing.bezier(0.95, 0.1, 0.95, 1);
const CUSTOMIZE = [
{ key: "target", label: "Прогресс", type: "slider", min: 0, max: 100, step: 1, unit: "%", default: 72 },
{ key: "fillDuration", label: "Заполнение", type: "slider", min: 200, max: 5000, step: 100, unit: "ms", default: 2000 },
{ key: "size", label: "Размер", type: "slider", min: 40, max: 240, step: 2, unit: "px", default: 120 },
{ key: "strokeWidth", label: "Толщина", type: "slider", min: 2, max: 30, step: 1, unit: "px", default: 12 },
{ key: "color", label: "Цвет дуги", type: "color", default: "#ffffff" },
{ key: "background", label: "Фон", type: "color", default: "#0a0a0a" },
] as const;
export default function App() {
const custom = useCustomize(CUSTOMIZE);
const progress = useSharedValue(0);
const fill = { easing: FILL_EASING, duration: custom.fillDuration };
useEffect(() => {
progress.value = withTiming(custom.target, fill);
}, [custom.target, custom.fillDuration]);
useAutoplay(
async ({ wait }) => {
await wait(1800);
progress.value = withTiming(0, { duration: 400 });
await wait(700);
progress.value = withTiming(custom.target, fill);
await wait(custom.fillDuration);
},
{ startDelayMs: 2000 },
);
return (
<Showcase>
<GestureHandlerRootView
style={[styles.container, { backgroundColor: custom.background }]}
>
<StatusBar style="light" />
<View>
<CircularProgress
progress={progress}
size={custom.size}
strokeWidth={custom.strokeWidth}
progressCircleColor={custom.color}
outerCircleColor="rgba(255,255,255,0.15)"
backgroundColor="#0000000f"
renderIcon={() => <></>}
/>
</View>
</GestureHandlerRootView>
</Showcase>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#0a0a0a",
alignItems: "center",
justifyContent: "center",
},
});progressТип SharedValue<number>
size?Тип number
strokeWidth?Тип number
outerCircleColor?Тип string
progressCircleColor?Тип string
backgroundColor?Тип string
onPress?Тип () => void
gap?Тип number
renderIcon?Тип () => ReactNode