如何用Reanimated 2实现多段延迟淡入文本?排查Lottie动画异常
启动页代码错误分析与优雅实现方案
代码中的核心错误
- 函数组件误用
this:函数组件不存在this上下文,代码中用this.anim存储Lottie实例引用完全无效,导致Lottie播放逻辑不稳定,甚至触发报错。 - 未清理的定时器:直接在函数体中声明
setTimeout,组件每次渲染都会创建新的定时器;且组件卸载后定时器仍可能执行,引发无效导航或内存泄漏,这也是登录页Lottie动画异常的潜在诱因。 - 动画与跳转逻辑脱节:固定时长的
setTimeout无法和Reanimated的entering动画状态联动,可能出现动画未完成就跳转的情况,导致体验不一致。
优雅实现方案
以下是修正后的代码,同时优化了副作用管理和动画逻辑:
import React, { useRef, useEffect } from 'react'; import { Text, ImageBackground } from 'react-native'; import Animated, { FadeIn } from 'react-native-reanimated'; import Lottie from 'lottie-react-native'; export default function SplashScreen({ navigation }) { const lottieRef = useRef(null); const navigationTimeoutRef = useRef(null); useEffect(() => { // 延迟播放Lottie动画 const playLottieTimer = setTimeout(() => { lottieRef.current?.play(); }, 1000); // 延迟跳转至登录页 navigationTimeoutRef.current = setTimeout(() => { navigation.navigate("signIn"); }, 2100); // 组件卸载时清理所有定时器,避免内存泄漏 return () => { clearTimeout(playLottieTimer); clearTimeout(navigationTimeoutRef.current); }; }, [navigation]); return ( <ImageBackground source={require('../../assets/signin.jpg')} resizeMode={'cover'} style={{ flex: 1, justifyContent: "center", alignItems: "center", padding: 30 }}> <Animated.View entering={FadeIn.duration(500).delay(100)}> <Text style={{ fontSize: 35, color: 'white', letterSpacing: 5 }}>Welcome</Text> </Animated.View> <Animated.View entering={FadeIn.duration(500).delay(250)}> <Text style={{ fontSize: 25, marginTop: 68, color: "black", padding: 55 }}>to</Text> </Animated.View> <Lottie style={{ paddingTop: 70 }} source={require('../../assets/splash.json')} autoPlay={false} loop={false} speed={0.7} ref={lottieRef} /> <Animated.View entering={FadeIn.duration(600).delay(800)}> <Text style={{ letterSpacing: 2.5, fontSize: 75, paddingTop: 25, color: "#fff" }}>us</Text> </Animated.View> </ImageBackground> ); }
额外优化建议
如果想让跳转逻辑完全与动画状态同步(替代固定时长的定时器),可以利用Lottie的动画完成回调:
// 修改Lottie组件,添加onAnimationFinish回调 <Lottie style={{ paddingTop: 70 }} source={require('../../assets/splash.json')} autoPlay={false} loop={false} speed={0.7} ref={lottieRef} onAnimationFinish={() => { // 等Lottie动画结束后再跳转 navigation.navigate("signIn"); }} />
同时移除useEffect中的导航定时器,这样可以避免固定时长的误差,让启动页的动画流程更连贯。
内容的提问来源于stack exchange,提问作者Andras
相关产品推荐
相关产品推荐

