You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 22:09:24