反应本机动画,循环动画而无需在迭代后重置动画值

时间:2020-06-20 20:29:18

标签: javascript react-native animation react-animated

React-Native Animated:如何循环播放动画,而不在每次循环后重置动画值。

我一直在努力寻找一种循环React Native Animations而不将动画值重新设置为其初始值的方法。

例如,我制作了一个简单的“ Sway”动画,该动画可以左右移动组件

  let animationX = new Animated.Value(0);

  const left = (toValue) => Animated.timing(animationX, {toValue: -toValue, duration: 1500})
  const right = (toValue) => Animated.timing(animationX, {toValue, duration: 1500})

  const startSwayAnimation = () => {
    Animated.loop(
      Animated.sequence([
        left(100),
        right(100),
      ])
    ).start()
  }

问题是我的animationX变量在每个循环后都重置为0。 我没有找到关于如何在不重置值的情况下循环播放动画的任何有用资源,尽管在github上有两个严重的问题:

https://github.com/facebook/react-native/issues/18028 https://github.com/facebook/react-native/issues/20560

我快要考虑询问SO了,但是后来我尝试创建一个递归函数来循环播放动画,效果很好

万一其他人正在为此而苦苦挣扎,或者知道更好的解决方案(也许我不知道的Animated.loop的一些配置),我决定在SO上共享它。

2 个答案:

答案 0 :(得分:1)

解决上述问题的内存泄漏解决方法!

我以前的实现导致内存泄漏 我还想出了如何使其在自定义钩子中可重用!

const useLoopAnimation = (animationFn) => {
  // loopAnimation halts when changing state variables (using useState) for unknown reason
  // so use a let variable instead.
  let stopped = false;
  const loopAnimation = () => {
    if (stopped) return false;
    animationFn().start(() => loopAnimation());
  };

  // this runs on component dismount to stop the recursive loop.
  useEffect(() => () => {
    stopped = true;
  });
  return loopAnimation;
};

,然后在组件中像这样使用它

  const loopAnimation = useLoopAnimation(() =>
    Animated.sequence([left(100), right(100)])
  );

答案 1 :(得分:0)

您可以使用递归通过在开始回调中调用相同的函数来一遍又一遍地调用相同的Animation

  let animationX = new Animated.Value(0);
  const left = (toValue: number) =>
    Animated.timing(animationX, { toValue: -toValue, duration: 1500 });
  const right = (toValue: number) =>
    Animated.timing(animationX, { toValue, duration: 1500 });

    const loopSway = () => {
        Animated.sequence([
          left(100),
          right(100),
        ]).start(() => loopSway())
    }

但是,我无法创建可重用的loopAnimation函数。 当我尝试时,出现错误undefined is not an object (evaluating 'animations[current].start')

    const sway = Animated.sequence([
      left(100),
      right(100),
    ])

    const loopAnimation = (animation) => {
        animation.start(() => loopAnimation(animation))
    }

    const loopSway = loopAnimation(sway)

React Native Animated中似乎有一些副作用,不允许您将动画分配为常量:(

我尝试克隆动画

    const loopAnimation = (animation) => {
        const animationClone = {...animation}
        animation.start(() => loopAnimation(animationClone))
    }

我尝试将动画设置为状态值。

但是两者都没有成功,因此如果有人对如何使此fn可重用有所了解,将不胜感激!