如何使用动画制作React Native中的循环图像背景

时间:2017-11-01 23:36:20

标签: react-native

我最初使用setInterval()来制作循环图像背景,方法是让两个图像从x:0开始,另一个从x: imageWidth开始,然后按以下方式更新它们:

  _updateBackgroundImage = () => {
    this.setState({
      background1Left: this.state.background1Left > (-this.backgroundImageWidth) ? this.state.background1Left-3 : this.backgroundImageWidth,
      background2Left: this.state.background2Left > (-this.backgroundImageWidth) ? this.state.background2Left-3 : this.backgroundImageWidth,
    })
  }

它工作得很好但是setInterval()导致与在线库中的另一个组件发生冲突,因此我转而使用Animated API并拥有以下代码:

this.translateValue = new Animated.Value(0)

  translate() {
    this.translateValue.setValue(0)
    Animated.timing(
      this.translateValue,
      {
        toValue: 1,
        duration: 14000,
        easing: Easing.linear
      }
    ).start(()=>this.translate())
  }
const translateBackgroundImage1 = this.translateValue.interpolate({
  inputRange: [0, 1],
  outputRange: [0, -this.backgroundImageWidth]
})
const translateBackgroundImage2 = this.translateValue.interpolate({
  inputRange: [0, 1],
  outputRange: [this.backgroundImageWidth, -this.backgroundImageWidth]
})


return (
  <View style={{flex:1}}>

   <Animated.Image
      style={{
        flex: 1,
        position: 'absolute',
        left: translateBackgroundImage1,
         }}
      resizeMode={Image.resizeMode.cover}
      source={this.backgroundImage}
    />
    <Animated.Image
      style={{
        flex: 1,
        position: 'absolute',
        left: translateBackgroundImage2,
         }}
      resizeMode={Image.resizeMode.cover}
      source={this.backgroundImage}
    />

要应用我用于setInterval()的相同逻辑,我会translateBackgroundImage1从第一个循环中的x:0开始,然后从x: ImageWidth开始

我不确定如何使用Animated

实现此功能

2 个答案:

答案 0 :(得分:1)

我最终找到了解决方案。它不是很干净但有效。

我基本上从同一张图片中加载了两个Animated.image。然后我有translateValue1,它控制第一张图像的左侧位置。然后根据translateValue1,我们translateValue2的{​​{1}} offsetimagewidth控制第二张图片的左侧位置。

当第一张图像即将从屏幕退出时,它将转到屏幕的最右侧,同时第二张图像将移动到第一张图像的正面,因此我们需要更改translateValue2offset。因此,在两个动画函数中都有一个-imagewidth方法。

在构造函数中我有以下变量:

setState

然后我有这两个函数,每个函数控制循环的一半:

constructor(props) {
    super(props);

    this.backgroundImage = require('../assets/images/graidenttPastel.jpg'); 
    this.backgroundImageWidth = resolveAssetSource(this.backgroundImage).width;
    this.translateXValue1 = new Animated.Value(-1);
    this.translateXValue2 = new Animated.Value(0);
    this.animationLength = 20000;

    this.state = {
      translateXValue2Offset: this.backgroundImageWidth,
      stopAnimation: false,
    }

最后在 translateXFirstHalfLoop() { this.translateXValue1.setValue(-1); this.setState({translateXValue2Offset: this.backgroundImageWidth}); this.firstHalfLoop = Animated.timing( this.translateXValue1, { toValue: -this.backgroundImageWidth, duration: this.animationLength/2, easing: Easing.linear } ).start(() => { if(this.state.stopAnimation === false) { this.translateXSecondHalfLoop() } }) } translateXSecondHalfLoop() { this.translateXValue1.setValue(this.backgroundImageWidth); this.setState({translateXValue2Offset: -this.backgroundImageWidth}); this.secondHalfLoop = Animated.timing( this.translateXValue1, { toValue: 0, duration: this.animationLength/2, easing: Easing.linear } ).start(() => { if(this.state.stopAnimation === false) { this.translateXFirstHalfLoop() } }) } 方法中,我有两个render(),如下所示:

Animated.Image

由于每个半循环函数都调用另一个,我们需要在卸载此组件之前停止它们,因此我们在下面添加了以下额外步骤:

  render() {
    this.translateXValue2 = Animated.add(this.translateXValue1, this.state.translateXValue2Offset);

    return (
      <SafeAreaView
        style={[{backgroundColor: THEME_COLOR, flex: 1}]}
        forceInset={{ bottom: 'never' }}>
        <Animated.Image
          style={{
            position: 'absolute',
            left: this.translateXValue1,
             }}
          resizestate={Image.resizeMode.cover}
          source={this.backgroundImage}
        />
        <Animated.Image
          style={{
            position: 'absolute',
            left: this.translateXValue2,
             }}
          resizestate={Image.resizeMode.cover}
          source={this.backgroundImage}
        />
        <View style={{flex:1}}>

          {this._renderScreenContent()}

        </View>
      </SafeAreaView>
    );
  }

答案 1 :(得分:0)

如果您想为ImageBackground制作动画,请尝试

var AnimatedImage = Animated.createAnimatedComponent(ImageBackground)