"use client" import React, { useEffect, useState, useCallback, useMemo } from "react" import { type LayoutChangeEvent, View } from "react-native" import Animated, { useSharedValue, useAnimatedStyle, withRepeat, withTiming, Easing, withSequence, withDelay, } from "react-native-reanimated" import Auto from "svg/Auto" import Avia from "svg/Avia" type Props = { type: "auto" | "avia" } const AnimatedIcon = ({ type }: Props) => { const translateX = useSharedValue(0) const translateY = useSharedValue(0) const rotateY = useSharedValue(0) const direction = useSharedValue(1) const [containerWidth, setContainerWidth] = useState(0) const iconSize = 40 const onLayout = useCallback((event: LayoutChangeEvent) => { const { width } = event.nativeEvent.layout setContainerWidth(width) }, []); const animationConfig = useMemo(() => ({ duration: 4000, easing: Easing.linear, rotationDuration: 300, arcHeight: -30, }), []); const createXAnimation = useCallback((maxX: number) => { return withRepeat( withSequence( withTiming(maxX, { duration: animationConfig.duration, easing: animationConfig.easing }, () => { direction.value = -1; rotateY.value = withTiming(180, { duration: animationConfig.rotationDuration }); }), withTiming(0, { duration: animationConfig.duration, easing: animationConfig.easing }, () => { direction.value = 1; rotateY.value = withTiming(0, { duration: animationConfig.rotationDuration }); }) ), -1 ); }, [animationConfig, direction, rotateY]); const createYAnimation = useCallback(() => { if (type === "avia") { return withRepeat( withSequence( withTiming(animationConfig.arcHeight, { duration: animationConfig.duration / 2, easing: Easing.out(Easing.quad), }), withTiming(0, { duration: animationConfig.duration / 2, easing: Easing.in(Easing.quad), }), withTiming(animationConfig.arcHeight, { duration: animationConfig.duration / 2, easing: Easing.out(Easing.quad), }), withTiming(0, { duration: animationConfig.duration / 2, easing: Easing.in(Easing.quad), }) ), -1 ); } return withTiming(0, { duration: 100 }); }, [type, animationConfig]); useEffect(() => { if (containerWidth === 0) return; const maxX = containerWidth - iconSize; translateX.value = createXAnimation(maxX); translateY.value = createYAnimation(); }, [containerWidth, type, createXAnimation, createYAnimation, translateX, translateY]); const animatedStyle = useAnimatedStyle(() => { return { transform: [ { translateX: translateX.value }, { translateY: translateY.value }, { rotateY: `${rotateY.value}deg` }, ], } }); const containerStyle = useMemo(() => ({ height: 100, justifyContent: "center" as const, backgroundColor: "transparent" as const, position: "relative" as const, }), []); const trackStyle = useMemo(() => ({ height: 2, backgroundColor: "#28A7E850", position: "absolute" as const, top: 25, left: 0, right: 0, }), []); const iconContainerStyle = useMemo(() => ({ position: "absolute" as const, top: 0, height: iconSize, width: iconSize, }), [iconSize]); const renderIcon = useMemo(() => { if (type === "auto") { return ; } return ; }, [type, iconSize]); return ( {renderIcon} ) } export default AnimatedIcon;