React Native Lottie 动画仅在第一次点击时播放

React Native Lottie Animation Only Plays On First Tap

基本上,我想在每次点击时播放 lottie 动画。这是我的 UI 乐蒂动画代码:

<Pressable onPress={playGame}>

<LottieView
   ref={loseAnimationRef}
   style={styles.egg}
   source={Lost}
   autoPlay={false}
   loop={false}
   onAnimationFinish={() => {
      resetAnimation();
   }}
/>

</Pressable>

这是我的 lottie 动画状态代码:

  const loseAnimationRef = useRef(null);

  const playGame = async () => {
    await mainGameLogicUC();
    playAnimation()
  };

  const playAnimation = () => {
      loseAnimationRef.current.play()
  }

  const resetAnimation = () => {
      loseAnimationRef.current.reset()
  }

第一次点击时,动画播放得非常好。但在所有其他水龙头上,动画不会播放。我尝试在 onAnimationFinish 中暂停动画然后继续播放,但这也没有用。我错过了什么吗?

编辑

我去掉了 onAnimationFinish 中的 resetAnimation(),这解决了最初的问题。但问题是,我希望 每次都将动画重置到开头。为什么我重置动画时它会中断?

你试过这样的东西吗?

const animationRef = useRef<AnimatedLottieView>()
const isAnimating = useRef<boolean>(false)

const onAnimationPress = () => {
    if (!isAnimating.current) {
        isAnimating.current = true
        animationRef.current.play()
    }
}

<TouchableWithoutFeedback onPress={onAnimationPress}>
    <AnimatedLottieView
        source={source}
        ref={animationRef}
        autoPlay={false}
        loop={false}
        onAnimationFinish={() => {
            isAnimating.current = false
            animationRef.current.reset()
        }}
    />
</TouchableWithoutFeedback>

几天后回到这个问题后,我找到了解决方案

播放 lottie 动画似乎被认为是副作用,因此,编辑对动画的引用应该在 useEffect 挂钩

中完成

对我有用的解决方案:

(同样,在此代码中,我 希望 动画在用户再次点击屏幕之前重置到开头。

state code

  const isMounted = useRef(false);

  const [isWonAnimationShowing, setIsWonAnimationShowing] = useState(false);
  const [isAnimationPlaying, setIsAnimationPlaying] = useState(false);
  const loseAnimationRef = useRef(null);
  const winAnimationRef = useRef(null);

  useEffect(() => {
    if (isMounted.current) {
      if (isAnimationPlaying) {
        _playAnimation();
      } else {
        _resetAnimation();
      }
    } else {
      isMounted.current = true;
    }
  }, [isAnimationPlaying]);


  const playAnimation = () => {
    setIsAnimationPlaying(true);
  };


  const _playAnimation = () => {
    if (isWonAnimationShowing) {
      winAnimationRef.current.play();
    } else {
      loseAnimationRef.current.play();
    }
  };


  const resetAnimation = () => {
    setIsAnimationPlaying(false);
  };


  const _resetAnimation = () => {
    if (isWonAnimationShowing) {
      winAnimationRef.current.reset();
    } else {
      loseAnimationRef.current.reset();
    }
  };

UI code

    <View style={styles.body}>
      <Pressable disabled={isAnimationPlaying} onPress={playGame}>
        {isWonAnimationShowing ? (
          <LottieView
            ref={winAnimationRef}
            style={styles.egg}
            source={Won}
            autoPlay={false}
            loop={false}
            onAnimationFinish={() => {
              resetAnimation();
            }}
          />
        ) : (
          <LottieView
            ref={loseAnimationRef}
            style={styles.egg}
            source={Lost}
            autoPlay={false}
            loop={false}
            onAnimationFinish={() => {
              resetAnimation();
            }}
          />
        )}
      </Pressable>
    </View>