import { useCallback, useEffect, useRef, useState } from 'react'; import { Image, Text, View } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { JIUZU_SPLASH_GIF_URL, JIUZU_SPLASH_MARK_URL } from '@dukang/shared-types'; import { markJiuzuSplashPlayed } from '../lib/jiuzu-splash'; const CHARS = ['酒', '祖', '杜', '康'] as const; const SPLASH_NAV_BG = '#140808'; const HOME_NAV_BG = '#FAF9F7'; /** GIF 21 帧 × 80ms,略提前淡出避免循环 */ const GIF_MS = 1650; const GIF_FADE_MS = 350; /** 四字显现并升到偏上位置 */ const TITLE_MS = 2400; /** 副标题在四字到位后再升起 */ const SUB_DELAY_MS = 2300; const SUB_MS = 1400; const HOLD_MS = 900; const FADE_MS = 800; const FADE_AT_MS = GIF_MS + SUB_DELAY_MS + SUB_MS + HOLD_MS; type JiuzuSplashProps = { onDone: () => void; }; function applySplashChrome() { try { void Taro.hideTabBar({ animation: false }); } catch { /* H5 无原生 TabBar */ } void Taro.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: SPLASH_NAV_BG, animation: { duration: 200, timingFunc: 'easeIn' }, }).catch(() => {}); } function restoreChrome() { try { void Taro.showTabBar({ animation: false }); } catch { /* H5 无原生 TabBar */ } void Taro.setNavigationBarColor({ frontColor: '#000000', backgroundColor: HOME_NAV_BG, animation: { duration: 200, timingFunc: 'easeOut' }, }).catch(() => {}); } export default function JiuzuSplash({ onDone }: JiuzuSplashProps) { const finishedRef = useRef(false); const fadingRef = useRef(false); const onDoneRef = useRef(onDone); onDoneRef.current = onDone; const [leaving, setLeaving] = useState(false); const [gifDone, setGifDone] = useState(false); const [gifGone, setGifGone] = useState(false); const finish = useCallback(() => { if (finishedRef.current) return; finishedRef.current = true; restoreChrome(); onDoneRef.current(); }, []); const beginExit = useCallback(() => { if (fadingRef.current || finishedRef.current) return; fadingRef.current = true; setLeaving(true); setTimeout(finish, FADE_MS); }, [finish]); useEffect(() => { markJiuzuSplashPlayed(); applySplashChrome(); const gifTimer = setTimeout(() => setGifDone(true), GIF_MS); const gifGoneTimer = setTimeout(() => setGifGone(true), GIF_MS + GIF_FADE_MS); const exitTimer = setTimeout(beginExit, FADE_AT_MS); return () => { clearTimeout(gifTimer); clearTimeout(gifGoneTimer); clearTimeout(exitTimer); if (!finishedRef.current) restoreChrome(); }; }, [beginExit]); return ( { e.stopPropagation?.(); }} > {gifGone ? null : ( )} {CHARS.map((ch) => ( {ch} ))} 千年酒祖 · 杜康好客 跳过 ); }