用新动画重复动画 api

Repeat animation with new animated api

React-native introduce new Animated API, 我想制作一个循环动画,例如气泡放大然后缩小并重复那个过程。

但是我想不通。我试过写一些像下面这样的代码

class TestProject extends React.Component {

  constructor(): void {
    super();
    this.state = {
      bounceValue: new Animated.Value(0),
      v: 1,
    };
  }

  componentDidMount() {
    this.state.bounceValue.setValue(1.5);

    let animation = Animated.timing(this.state.bounceValue, {
      toValue: this.state.v,
    });

    setInterval(() => {
      animation.stop();

      if (this.state.flag) {
        this.state.v = 0.5;
        this.state.bounceValue.setValue(0.5);
      }
      else {
        this.state.v = 1.5;
        this.state.bounceValue.setValue(1.5);
      }

      animation.start();
    }, 5000);

  }

  render(): ReactElement {
    return (
      <View style={styles.imageContainer}>
        <Image
          style={styles.image}
          source={{uri: 'http://image142-c.poco.cn/best_pocoers/20130517/91062013051716553599334223.jpg'}}
        />
        <Animated.Text
          style={[
            styles.test,
            {transform: [
              {scale: this.state.bounceValue},
            ],}
          ]
          }>
          haha
        </Animated.Text>
      </View>
    );
  }

}

但效果不是很好。

如有任何建议,我们将不胜感激。

Animated api 似乎暂时不支持 'looping'。

我设法在动画结束后再次启动动画。

startAnimation() {
  Animated.timing(this._animatedValue, {
    toValue: 100,
    duration: 1000,
  }).start(() => {
    this.startAnimation();
  });
}

期待更好的解决方案...

我用的是sequence的方法,传一个动画数组循环然后repeat这个函数

//this.state.animatedStartValue = 0;

function cycleAnimation() {
  Animated.sequence([
    Animated.timing(this.state.animatedStartValue, {
      toValue: 1,
      duration: 500,
      delay: 1000
    }),
    Animated.timing(this.state.animatedStartValue, {
      toValue: 0,
      duration: 500
    })
  ]).start(() => {
    cycleAnimation();
  });
}

如果我自己切换动画,它会淡出 in/out,但是我将它放在底座上以模仿活动状态或热点式按钮

  <TouchableOpacity>
    <Animated.Image
      source={activeImageSource}
      style={this.state.animatedStartValue}}
    />
    <Image source={nonActiveImageSource}
    />
  </TouchableOpacity>

React Native Sequence Documentation

您可以设置另一个动画然后再次调用动画:

我做的一个淡入淡出文本的例子:

  textAnimate: function() {
    Animated.timing(
      this.state.textOpacity,
      {
        toValue: 0.3,                         
        duration: 500, 
      }
    ).start(() => {
      Animated.timing(  
        this.state.textOpacity,            
        {
          toValue: 1,                    
          duration: 500,          
        }
      ).start(() => {
          this.textAnimate();
        });
    });    
  },

  componentDidMount: function() {
    this.state.textOpacity.setValue(1)
    this.textAnimate();
  },

@bcomerford 回答的改进版本[​​=11=]

//this.state.animatedStartValue = 0;

function cycleAnimation() {
  Animated.sequence([
    Animated.timing(this.state.animatedStartValue, {
      toValue: 1,
      duration: 500,
      delay: 1000
    }),
    Animated.timing(this.state.animatedStartValue, {
      toValue: 0,
      duration: 500
   })
  ]).start(event => {
    if (event.finished) {
      cycleAnimation();
    }
  });
}

现在 loop animation 可用:

Animated.loop(
  Animated.sequence([
    Animated.timing(this.state.animatedStartValue, {
      toValue: 1,
      duration: 500,
      delay: 1000
    }),
    Animated.timing(this.state.animatedStartValue, {
      toValue: 0,
      duration: 500
    })
  ]),
  {
    iterations: 4
  }
).start()

尝试这样的事情:

componentDidMount() {
    this.bootAnimation();
  }

  bootAnimation() {
    this.animation = Animated.loop(
      Animated.timing(this.state.progress, {
        toValue: 1,
        duration: 5000
      })
    ).start();
  }

不确定它是否有问题,但我使用这个:

Animated.spring(this.state.rotation, {
  toValue: 5,
  stiffness: 220, // the higher value, the faster the animation
  damping: 0.000001, // never stop wiggle wiggle wiggle
}).start();

它正在创建 spring 永远不会(从技术上讲,在非常非常长的时间内)停止挥手的动画。

对于我的大多数情况来说,这就足够了。它还具有出色的性能,因为它在动画期间不需要任何 JS 踩踏动作。

如果你最终想优雅地停止它:

Animated.spring(this.state.rotation, {
  toValue: 0,
  stiffness: 220, // the higher value, the faster the animation
  damping: 10, // never stop wiggle wiggle wiggle
}).start();

它会很好地 'slow down' 直到它停止。

这是另一个使用钩子和 iterations 设置为 "infinity" 的无限动画示例。避免在之前的答案中使用递归,这有时会导致我们在 e2e 测试期间出现奇怪的行为。

  const rotation = React.useRef(new Animated.Value(0)).current;

  function runAnimation() {
    return Animated.loop(
      Animated.timing(rotation, {
        toValue: 1,
        duration: 1200,
        easing: Easing.linear,
        useNativeDriver: true,
      }),
      {resetBeforeIteration: true, iterations: Number.MAX_SAFE_INTEGER},
    );
  }

  React.useEffect(() => {
    const animation = runAnimation();
    return () => animation.stop();
  }, []);