import IP from '@/assets/icons/svg/ip.svg'; import { checkAuthStatus } from '@/lib/auth'; import { useRouter } from 'expo-router'; import React, { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Animated, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { useSafeAreaInsets } from "react-native-safe-area-context"; export default function HomeScreen() { const router = useRouter(); const { t } = useTranslation(); const insets = useSafeAreaInsets(); const [isLoading, setIsLoading] = useState(false); // 动画值 const fadeAnim = useRef(new Animated.Value(0)).current; // IP图标的淡入动画 const shakeAnim = useRef(new Animated.Value(0)).current; // IP图标的摇晃动画 const animationRef = useRef(null); // 动画引用 const descriptionAnim = useRef(new Animated.Value(0)).current; // 描述文本的淡入动画 const buttonAnim = useRef(new Animated.Value(0)).current; // 按钮的淡入动画 const buttonShakeAnim = useRef(new Animated.Value(0)).current; // 按钮的摇晃动画 const buttonLoopAnim = useRef(null); // 按钮循环动画引用 // 文本行动画值 const [textAnimations] = useState(() => ({ line1: new Animated.Value(0), // 第一行文本动画 line2: new Animated.Value(0), // 第二行文本动画 line3: new Animated.Value(0), // 第三行文本动画 subtitle: new Animated.Value(0), // 副标题动画 })); // 添加挥手动画值 const waveAnim = useRef(new Animated.Value(0)).current; // 启动IP图标摇晃动画 const startShaking = () => { // 停止任何正在进行的动画 if (animationRef.current) { animationRef.current.stop(); } // 创建动画序列 const sequence = Animated.sequence([ // 第一次左右摇晃 Animated.timing(shakeAnim, { toValue: 1, duration: 300, useNativeDriver: true, }), Animated.timing(shakeAnim, { toValue: -1, duration: 300, useNativeDriver: true, }), // 第二次左右摇晃 Animated.timing(shakeAnim, { toValue: 1, duration: 300, useNativeDriver: true, }), Animated.timing(shakeAnim, { toValue: -1, duration: 300, useNativeDriver: true, }), // 回到中心位置 Animated.timing(shakeAnim, { toValue: 0, duration: 200, useNativeDriver: true, }), // 1秒延迟 Animated.delay(1000), ]); // 循环播放动画序列 animationRef.current = Animated.loop(sequence); animationRef.current.start(); }; // 启动文本动画 const startTextAnimations = () => { // 按顺序延迟启动每行文本动画 return new Promise((resolve) => { Animated.stagger(300, [ Animated.timing(textAnimations.line1, { toValue: 1, duration: 500, useNativeDriver: true, }), Animated.timing(textAnimations.line2, { toValue: 1, duration: 500, useNativeDriver: true, }), Animated.timing(textAnimations.line3, { toValue: 1, duration: 500, useNativeDriver: true, }), Animated.timing(textAnimations.subtitle, { toValue: 1, duration: 500, useNativeDriver: true, }), ]).start(() => resolve()); }); }; // 启动描述文本动画 const startDescriptionAnimation = () => { // IP图标显示后淡入描述文本 return new Promise((resolve) => { Animated.sequence([ Animated.delay(200), // IP图标显示后延迟200ms Animated.timing(descriptionAnim, { toValue: 1, duration: 800, useNativeDriver: true, }) ]).start(() => resolve()); }); }; // 启动按钮动画 const startButtonAnimation = () => { // 首先淡入按钮 Animated.sequence([ Animated.timing(buttonAnim, { toValue: 1, duration: 800, useNativeDriver: true, }) ]).start(() => { // 淡入完成后开始循环摇晃动画 startButtonShakeLoop(); }); }; // 启动按钮循环摇晃动画 const startButtonShakeLoop = () => { // 停止任何正在进行的动画 if (buttonLoopAnim.current) { buttonLoopAnim.current.stop(); } // 创建摇晃动画序列 const shakeSequence = Animated.sequence([ // 向右摇晃 Animated.timing(buttonShakeAnim, { toValue: 1, duration: 100, useNativeDriver: true, }), // 向左摇晃 Animated.timing(buttonShakeAnim, { toValue: -1, duration: 100, useNativeDriver: true, }), // 再次向右摇晃 Animated.timing(buttonShakeAnim, { toValue: 1, duration: 100, useNativeDriver: true, }), // 回到中心位置 Animated.timing(buttonShakeAnim, { toValue: 0, duration: 100, useNativeDriver: true, }), // 暂停3秒 Animated.delay(3000) ]); // 循环播放动画序列 buttonLoopAnim.current = Animated.loop(shakeSequence); buttonLoopAnim.current.start(); }; // 启动挥手动画 const startWaveAnimation = () => { // 创建循环动画:左右摇摆 Animated.loop( Animated.sequence([ Animated.timing(waveAnim, { toValue: 1, duration: 500, useNativeDriver: true, }), Animated.timing(waveAnim, { toValue: -1, duration: 500, useNativeDriver: true, }), Animated.timing(waveAnim, { toValue: 0, duration: 500, useNativeDriver: true, }), Animated.delay(1000), // 暂停1秒 ]) ).start(); }; // 组件挂载时启动动画 useEffect(() => { setIsLoading(true); checkAuthStatus(router, () => { router.replace('/ask') }, false).then(() => { setIsLoading(false); }).catch(() => { setIsLoading(false); }); // IP图标的淡入动画 Animated.timing(fadeAnim, { toValue: 1, duration: 1000, useNativeDriver: true, }).start(() => { // 淡入完成后开始摇晃动画 startShaking(); // IP显示后开始文本动画 startTextAnimations() .then(() => startDescriptionAnimation()) .then(() => startButtonAnimation()) .catch(console.error); // 启动挥手动画 startWaveAnimation(); }); // 组件卸载时清理动画 return () => { if (buttonLoopAnim.current) { buttonLoopAnim.current.stop(); } if (animationRef.current) { animationRef.current.stop(); } }; }, []); // 动画样式 const animatedStyle = { opacity: fadeAnim, transform: [ { translateX: shakeAnim.interpolate({ inputRange: [-1, 1], outputRange: [-2, 2], }) }, { rotate: shakeAnim.interpolate({ inputRange: [-1, 1], outputRange: ['-2deg', '2deg'], }), }, ], }; // 旋转动画插值 const rotate = waveAnim.interpolate({ inputRange: [-1, 0, 1], outputRange: ['-15deg', '0deg', '15deg'], }); if (isLoading) { return ( {t('common.loading')} ); } return ( {/* 标题区域 */} {t('auth.welcomeAwaken.awaken', { ns: 'login' })} {t('auth.welcomeAwaken.your', { ns: 'login' })} {t('auth.welcomeAwaken.pm', { ns: 'login' })} {t('auth.welcomeAwaken.slogan', { ns: 'login' })} {/* Animated IP */} {/* 介绍文本 */} {t('auth.welcomeAwaken.gallery', { ns: 'login' })} {"\n"} {t('auth.welcomeAwaken.back', { ns: 'login' })} {/* 唤醒按钮 */} { router.push('/login'); }} activeOpacity={0.8} > {t('auth.welcomeAwaken.awake', { ns: 'login' })} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#FFB645', }, loadingContainer: { flex: 1, backgroundColor: '#FFB645', justifyContent: 'center', alignItems: 'center', }, loadingText: { color: '#FFFFFF', fontSize: 16, }, contentContainer: { flex: 1, backgroundColor: '#FFB645', paddingHorizontal: 16, paddingBottom: 32, }, headerContainer: { marginBottom: 40, width: '100%', paddingHorizontal: 20, }, titleText: { color: '#FFFFFF', fontSize: 30, fontWeight: 'bold', marginBottom: 12, textAlign: 'left', lineHeight: 36, }, subtitleText: { color: 'rgba(255, 255, 255, 0.85)', fontSize: 16, textAlign: 'left', lineHeight: 24, }, ipContainer: { alignItems: 'center', marginBottom: 16, minHeight: 200, }, ipWrapper: { alignItems: 'center', justifyContent: 'center', }, descriptionText: { color: '#FFFFFF', fontSize: 16, textAlign: 'center', lineHeight: 24, opacity: 0.9, paddingHorizontal: 40, marginTop: -16, }, awakenButton: { backgroundColor: '#FFFFFF', borderRadius: 28, paddingVertical: 16, paddingHorizontal: 40, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 2, width: '100%', alignItems: 'center', marginTop: 24, }, buttonText: { color: '#4C320C', fontWeight: 'bold', fontSize: 18, }, });