【问题标题】:React Native - start Animated twice, an error start of undefinedReact Native - 两次启动动画,未定义的错误启动
【发布时间】:2019-12-06 07:37:00
【问题描述】:
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

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

【问题讨论】:

  • 为什么不把这个动画放到你的状态呢?
  • @AbdumutalAbdusamatov 将动画置于状态和不置于状态之间有区别吗?当我测试它时,两者都做同样的事情。所以我没有放。

标签: react-native react-animated react-native-animatable


【解决方案1】:

停止动画

this.animation.stopAnimation()

动画停止时可选获取回调

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

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

【讨论】:

    【解决方案2】:

    第一次调用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;
        },
      };
    };
    

    【讨论】:

      猜你喜欢
      • 2017-10-20
      • 2020-10-06
      • 2017-05-11
      • 2020-10-16
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 2013-04-21
      相关资源
      最近更新 更多