web-dev-qa-db-fra.com

Répéter l'animation avec une nouvelle api animée

React-native présente la nouvelle API Animated. Je souhaite créer une animation en boucle, telle qu’une réduction de bulle, puis une réduction et une répétition de cette progression.

Cependant, je ne peux pas le comprendre. J'ai essayé d'écrire du code comme ci-dessous

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>
    );
  }

}

mais ne fonctionne pas très bien.

Toute suggestion sera appréciée.

26
Pikaurd

Il y a maintenant animation en boucle disponible:

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()
88
silyevsk

J'utilise la méthode de la séquence pour transmettre un tableau d'animations au cycle, puis répéter la fonction.

//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();
  });
}

Si je bascule cette animation elle-même, les fondus seront fondus, mais je la superposerai au-dessus d'une base pour imiter un état actif ou un bouton de type point chaud

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

Documentation sur les séquences natives React

37
bcomerford

version améliorée de @bcomerford answer

//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();
    }
  });
}
16
joshblour

Essayez quelque chose comme ça:

componentDidMount() {
    this.bootAnimation();
  }

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

3
Miguel Cardenas

Pas sûr que ce soit hacky, mais j'utilise ceci:

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();

Cela crée une animation printanière qui ne cessera jamais (techniquement, pendant très très longtemps).

Pour la plupart de mes cas, c'était suffisant. En outre, il offre d'excellentes performances, car il ne nécessite aucune action de bande de roulement JS au cours de l'animation.

Si finalement vous souhaitez l'arrêter gracieusement:

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

Et ça va bien "ralentir" jusqu'à ce que ça s'arrête.

0
pie6k

Vous pouvez définir une autre animation puis appeler à nouveau l'animation:

Un exemple que j'ai fait pour afficher et masquer le texte en fondu:

  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();
  },
0
robinsonlam

Il semble que le "bouclage" ne soit pas supporté par l'API Animated pour le moment.

J'ai réussi à le faire en redémarrant l'animation à la fin.

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

 enter image description here

Dans l'attente d'une meilleure solution ...

0
xinthink