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

React中如何在 onPress 触发时让动画完成当前周期后停止

解决方案:让动画完成当前阶段后再停止

这个问题我之前也碰到过,直接用Animated.loop的stop()确实会粗暴中断动画,想要让动画完成当前关键阶段再停止,我们可以换个思路——手动控制动画循环,而不是依赖Animated.loop的内置循环逻辑。

核心思路

  1. 用useRef保存一个停止标记(shouldStop),因为我们需要即时修改和读取状态,且不需要触发组件重渲染。
  2. 将原来的Animated.loop拆分为递归调用的动画序列,在每个动画步骤完成后检查停止标记,决定是否继续执行后续动画。
  3. 点击停止按钮时,仅标记停止状态,让当前动画自然完成后自动终止。

完整代码示例

import React, { useRef } from 'react';
import { Animated, Button, Text, View } from 'react-native';

const Animated_2 = (props) => {
  // 初始化透明度动画值,默认完全不透明
  const animation = useRef(new Animated.Value(1)).current;
  // 停止标记,用useRef避免组件重渲染
  const shouldStop = useRef(false);

  const startAnimation = () => {
    // 启动前重置停止标记
    shouldStop.current = false;

    const runCycle = () => {
      // 如果已经标记停止,直接退出
      if (shouldStop.current) return;

      // 第一步:透明度从1降到0
      Animated.timing(animation, {
        toValue: 0,
        duration: props.duration,
        useNativeDriver: false,
      }).start(({ finished }) => {
        // 如果动画未正常完成(比如意外中断),直接退出
        if (!finished) return;

        // 检查是否需要停止:如果是,就终止,不再执行后续动画
        if (shouldStop.current) {
          return;
        }

        // 第二步:透明度从0回到1,完成后开启下一轮循环
        Animated.timing(animation, {
          toValue: 1,
          duration: props.duration,
          useNativeDriver: false,
        }).start(({ finished }) => {
          if (finished && !shouldStop.current) {
            runCycle();
          }
        });
      });
    };

    // 启动第一轮动画
    runCycle();
  };

  const stop = () => {
    // 仅标记停止状态,让当前动画自然完成后终止
    shouldStop.current = true;
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', gap: 16 }}>
      <Animated.Text style={{ opacity: animation, fontSize: 24 }}>
        闪烁的文本
      </Animated.Text>
      <Button title="启动动画" onPress={startAnimation} />
      <Button title="停止动画" onPress={stop} />
    </View>
  );
};

export default Animated_2;

关键细节说明

  • 停止逻辑:当你点击停止按钮时,shouldStop.current被设为true,当前正在执行的动画会继续完成(比如从40%透明度降到0%),完成后检查到停止标记,就不会再执行后续的动画步骤或下一轮循环。
  • 手动循环:通过递归调用runCycle来实现动画的重复,相比Animated.loop,这种方式让我们完全掌控每个动画阶段的执行逻辑,灵活实现“完成当前阶段再停止”的需求。
  • useRef的作用:用useRef保存shouldStop和animation,可以避免因状态更新触发的组件重渲染,同时保证状态读取和修改的即时性。

内容的提问来源于stack exchange,提问作者Jerry Seigle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 17:33:11