"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;