import React, { useRef, useMemo, memo } from 'react'; import type { ViewStyle } from 'react-native'; import { Animated } from 'react-native'; import { Svg, Circle } from 'react-native-svg'; import type { CircleProps } from 'react-native-svg/lib/typescript/elements/Circle'; import { getDefaultValue } from '../helpers'; import Theme from '../theme'; import { varCreator } from './style'; import useLoop from './useLoop'; const AnimatedCircle = // @ts-ignore Animated.createAnimatedComponent>(Circle); export interface CircularProps { /** * 图像大小 */ size?: number; /** * 颜色 */ color?: string; } const STROKE_WIDTH = 2; const Circular: React.FC = ({ size, color }) => { const TOKENS = Theme.useThemeTokens(); const CV = Theme.createVar(TOKENS, varCreator); const AnimatedCircle0Value = useRef(new Animated.Value(0)).current; const AnimatedCircle1Value = useRef(new Animated.Value(0)).current; const AnimatedCircle2Value = useRef(new Animated.Value(0)).current; size = getDefaultValue(size, CV.loading_icon_size); color = getDefaultValue(color, CV.loading_icon_color); const circle1Props = useMemo(() => { // @ts-ignore const center = Math.floor(size / 2); const radios = Math.floor(center - STROKE_WIDTH / 2); return { cy: center, cx: center, r: radios, }; }, [size]); const circle2Props = useMemo(() => { // @ts-ignore const center = Math.floor(size / 2); const radios = Math.floor(center - STROKE_WIDTH / 2 - center / 2); return { cy: center, cx: center, r: radios, }; }, [size]); const half1Circle = useMemo(() => circle1Props.r * Math.PI, [circle1Props.r]); const half2Circle = useMemo(() => circle2Props.r * Math.PI, [circle2Props.r]); useLoop(AnimatedCircle0Value, 0, { toValue: 1, duration: CV.loading_icon_animation_duration, }); useLoop(AnimatedCircle1Value, half1Circle, { toValue: -half1Circle * 2, duration: CV.loading_icon_animation_duration * 1.5, }); useLoop(AnimatedCircle2Value, half2Circle, { toValue: -half2Circle * 2, duration: CV.loading_icon_animation_duration * 2.5, }); const iconStyle: ViewStyle = { justifyContent: 'center', alignItems: 'center', width: size, height: size, transform: [ { rotateZ: AnimatedCircle0Value.interpolate({ inputRange: [0, 1], outputRange: ['-90deg', '270deg'], }) as any, }, ], }; return ( ); }; export default memo(Circular);