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>
基本上,我想在每次点击时播放 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>