aboutsummaryrefslogtreecommitdiff
path: root/src/components/animated-splash-screen.tsx
blob: 7ecfdef2053c1c6520c9a497a967a5618491eb5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import React, { useEffect } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import Animated, {
    useAnimatedStyle,
    useSharedValue,
    withTiming,
    withSpring,
    Easing,
    runOnJS,
    withDelay,
} from 'react-native-reanimated';
import { Colors } from '@/constants/theme';
import { LinearGradient } from 'expo-linear-gradient';

interface Props {
    isAppReady: boolean;
    onAnimationComplete: () => void;
}

export function AnimatedSplashScreen({ isAppReady, onAnimationComplete }: Props) {
    const opacity = useSharedValue(1);
    const scale = useSharedValue(1);
    const textOpacity = useSharedValue(0);
    const textTranslateY = useSharedValue(20);
    const logoScale = useSharedValue(0.8);

    useEffect(() => {
        textOpacity.value = withTiming(1, { duration: 1000 });
        textTranslateY.value = withSpring(0, { damping: 14, stiffness: 100 });
        logoScale.value = withSpring(1, { damping: 10, stiffness: 100 });
    }, []);

    useEffect(() => {
        if (isAppReady) {
            opacity.value = withDelay(
                600,
                withTiming(0, { duration: 700, easing: Easing.inOut(Easing.ease) }, (finished) => {
                    if (finished) {
                        runOnJS(onAnimationComplete)();
                    }
                })
            );

            scale.value = withDelay(
                600,
                withTiming(1.3, { duration: 700, easing: Easing.inOut(Easing.ease) })
            );
        }
    }, [isAppReady]);

    const animatedContainerStyle = useAnimatedStyle(() => ({
        opacity: opacity.value,
        transform: [{ scale: scale.value }],
    }));

    const animatedTextStyle = useAnimatedStyle(() => ({
        opacity: textOpacity.value,
        transform: [
            { translateY: textTranslateY.value },
            { scale: logoScale.value }
        ],
    }));

    return (
        <Animated.View style={[styles.container, animatedContainerStyle]}>
            <LinearGradient
                colors={['#0D2818', Colors.background]}
                style={StyleSheet.absoluteFill}
                start={{ x: 0, y: 0 }}
                end={{ x: 0, y: 1 }}
            />
            <Animated.View style={animatedTextStyle}>
                <Text style={styles.logoText}>YABA</Text>
                <Text style={styles.subText}>Finanças Pessoais</Text>
            </Animated.View>
        </Animated.View>
    );
}

const styles = StyleSheet.create({
    container: {
        ...StyleSheet.absoluteFill,
        justifyContent: 'center',
        alignItems: 'center',
        zIndex: 9999,
    },
    logoText: {
        fontFamily: 'Outfit_700Bold',
        fontSize: 72,
        color: Colors.white,
        letterSpacing: -2,
        textAlign: 'center',
    },
    subText: {
        fontFamily: 'DMSans_500Medium',
        fontSize: 16,
        color: Colors.primaryLight,
        letterSpacing: 2,
        textTransform: 'uppercase',
        textAlign: 'center',
        marginTop: 8,
    }
});