1
animation = new Animated.Value(0);

animationSequnce = Animated.sequence(
    [Animated.timing(this.animation, { toValue: 1 }),
      Animated.timing(this.animation, { toValue: 0, delay: 1000 }),
    ],
  );

startAnimation = () => {
  animationSequnce.start();
}

stopAnimation = () => {
  animationSequnce.stop();
}

我想开始animation sequence几次。

我通过编写startAnimation在按下按钮时调用的代码来测试它。动画在第一次运行时运行。在第一个动画完成后单击第二个按钮 Cannot read property 'start' of undefined时会发生错误。

startAnimation = () => {
  Animated.sequence(
    [Animated.timing(this.animation, { toValue: 1 }),
      Animated.timing(this.animation, { toValue: 0, delay: 1000 }),
    ],
  ).start();
} 

此更改startAnimation不会导致错误,但您将无法调用,因为它每次stopAnimation都会调用不同的。AnimationSequnce

多次使用动画的最佳方式是什么?

4

2 回答 2

0

停止动画

this.animation.stopAnimation()

动画停止时可选获取回调

this.animation.stopAnimation(this.callback())

或者

Animated.timing(
  this.animation
).stop();

于 2019-12-06T08:59:58.347 回答
0

第一次调用时Animated.sequence(),react native 会创建一个变量current,引用当前执行动画的索引,并存储在本地。

完成Animated.sequence().start()后,变量current不会被清除或重置为 0,因此第二次调用start()相同的序列动画时,数组索引超出范围并导致错误。

这是 react native 的一个隐藏 bug,下面是实现Animated.sequence

const sequence = function(
  animations: Array<CompositeAnimation>,
): CompositeAnimation {
  let current = 0;
  return {
    start: function(callback?: ?EndCallback) {
      const onComplete = function(result) {
        if (!result.finished) {
          callback && callback(result);
          return;
        }

        current++;

        if (current === animations.length) {
          callback && callback(result);
          return;
        }

        animations[current].start(onComplete);
      };

      if (animations.length === 0) {
        callback && callback({finished: true});
      } else {
        animations[current].start(onComplete);
      }
    },

    stop: function() {
      if (current < animations.length) {
        animations[current].stop();
      }
    },

    reset: function() {
      animations.forEach((animation, idx) => {
        if (idx <= current) {
          animation.reset();
        }
      });
      current = 0;
    },

    _startNativeLoop: function() {
      throw new Error(
        'Loops run using the native driver cannot contain Animated.sequence animations',
      );
    },

    _isUsingNativeDriver: function(): boolean {
      return false;
    },
  };
};

我的解决方案是定义一个自定义序列,并current在序列动画完成时手动重置为 0:

const sequence = function(
  animations: Array<CompositeAnimation>,
): CompositeAnimation {
  let current = 0;
  return {
    start: function(callback?: ?EndCallback) {
      const onComplete = function(result) {
        if (!result.finished) {
          current = 0;
          callback && callback(result);
          return;
        }

        current++;

        if (current === animations.length) {
          current = 0;
          callback && callback(result);
          return;
        }

        animations[current].start(onComplete);
      };

      if (animations.length === 0) {
        current = 0;
        callback && callback({finished: true});
      } else {
        animations[current].start(onComplete);
      }
    },

    stop: function() {
      if (current < animations.length) {
        animations[current].stop();
      }
    },

    reset: function() {
      animations.forEach((animation, idx) => {
        if (idx <= current) {
          animation.reset();
        }
      });
      current = 0;
    },

    _startNativeLoop: function() {
      throw new Error(
        'Loops run using the native driver cannot contain Animated.sequence animations',
      );
    },

    _isUsingNativeDriver: function(): boolean {
      return false;
    },
  };
};
于 2021-05-26T11:29:30.557 回答