misi06
misi06

Reputation: 289

Restarting animation with callback values

I have a looping animation which consist of few simple animations:

Animated.sequence([
        Animated.timing(this.state.animateUp, {toValue: 0, duration: 1500}),
        Animated.timing(this.state.fadeValue, {toValue: 1, duration: 500}),
        Animated.parallel([
          Animated.timing(this.state.opacity, {toValue: 0, duration: 1000}),
          Animated.timing(this.state.frontRotation, { toValue: 1, duration: 300, }),
        ]),

        Animated.timing(this.state.toWhite, {toValue: 1, duration: 1000, delay: 11500}),
      ]);

I am trying to stop them on touch with a function which stops each animation like:

this.state.animateUp.stopAnimation(this.callback) 

Then on second touch gesture i want to run the same animation with callback values. Is there any way of passing callback values back to the function and how it can be achieved?

Thanks in advance!

EDIT: Animation is not starting.

constructor(props) {
    super(props);
    this.state = {
      opacity: new Animated.Value(1),
      animateUp: new Animated.Value(-500),
      animateUpTime: new Animated.Value(1500),
      fadeValue: new Animated.Value(0),
      fadeValueTime: new Animated.Value(500),
      toWhite: new Animated.Value(0),
      toWhiteTime: new Animated.Value(11500),
      measurements: {},
      frontRotation: new Animated.Value(0),
      frontRotationTime: new Animated.Value(300),
      paused: false


    };
  }
  testPause(){
    this.animateUpListener = this.state.animateUp.addListener(({value}) => this.animateUpValue = value)
    this.fadeValueListener = this.state.fadeValue.addListener(({value}) => this.fadeValue = value)
    this.opacityListener = this.state.opacity.addListener(({value}) => this.opacityValue = value)
    this.frontRotationValueListener = this.state.frontRotation.addListener(({value}) => this.frontRotationValue = value)
    this.toWhiteListener = this.state.toWhite.addListener(({value}) => this.toWhiteValue = value)
    if(this.state.paused){
      this.state.animateUpTime = (1-this.animateUpValue)/1500
      this.state.fadeValueTime = (1-this.fadeValue)/500
      this.state.opacityValueTime = (1-this.opacityValue)/1000
      this.state.frontRotationTime = (1-this.frontRotationValue)/300
      this.state.toWhiteTime = (1-this.toWhiteValue)/11500


      this.setState({paused: false})
    } else {
      this.state.animateUp.stopAnimation();
      this.state.fadeValue.stopAnimation();
      this.state.opacity.stopAnimation();
      this.state.frontRotation.stopAnimation();
      this.state.toWhite.stopAnimation();
      this.setState({paused: true})}

}
  render() {
    var spin = this.state.frontRotation.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '90deg']
    })


    return (

    );
  }

   animateFront() {

    return Animated.sequence([
        Animated.timing(this.state.animateUp, {toValue: 0, duration: this.state.animateUpTime}),
        Animated.timing(this.state.fadeValue, {toValue: 1, duration: this.state.fadeValueTime}),
        Animated.parallel([
          Animated.timing(this.state.opacity, {toValue: 0, duration: this.state.opacityValueTime}),
          Animated.timing(this.state.frontRotation, { toValue: 1, duration: this.state.frontRotationTime, }),
        ]),

        Animated.timing(this.state.toWhite, {toValue: 1, duration: this.state.frontRotationTime, delay: 11500}),
      ]).start(() => this.restartAnimation());

   }

componentDidMount(){
  this.animateFront()
}
    restartAnimation(){
        this.animateUpValue = -500; //initialvalue
        this.fadeValue = 0; //initialvalue
        this.opacity = 1;
        this.toWhite = 0;
        this.frontRotation = 0;
        this.video.seek(0);
        this.state.animateUp.setValue(-500); //initialValue
        this.state.fadeValue.setValue(0); //initialValue
        this.state.opacity.setValue(1);
        this.state.toWhite.setValue(0);
        this.state.frontRotation.setValue(0);

    }
}

Upvotes: 1

Views: 3882

Answers (1)

Irfan Ayaz
Irfan Ayaz

Reputation: 797

You can implement pause and resume by calculating the final value and time remaining at pause time and resume animation with those values.

First of all, add listeners to your animated values and save the values.

this.animateUpListener = this.state.animateUp.addListener(({value}) => this.animateUpValue = value);
this.fadeValueListener = this.state.fadeValue.addListener(({value}) => this.fadeValue = value);

Similarly, add listeners for all other animations. After that, sequence code will look like this.

Animated.sequence([
        Animated.timing(this.state.animateUp, {toValue: 0, duration: 1500}),
        Animated.timing(this.state.fadeValue, {toValue: 1, duration: 500}),
        Animated.parallel([
          Animated.timing(this.state.opacity, {toValue: 0, duration: 1000}),
          Animated.timing(this.state.frontRotation, { toValue: 1, duration: 300, }),
        ]),

        Animated.timing(this.state.toWhite, {toValue: 1, duration: 1000, delay: 11500}),
      ]).start(() => this.restartAnimation());

When the button is pressed (first interaction), call stop animation on all animated values. At this point, values stored in listeners will have the value at which the animation was paused. For example, if animateUp had completed and fade was running, then this.fadeValue may have 0.25 etc value at this point. and this.state.animateUp will already have the final value i.e 0, so it won't run when we resume.

this.state.animateUp.stopAnimation();
this.state.fadeValue.stopAnimation();

Now you need to calculate the remaining time for the animation. if total time from fadeValue 0 to 1 is 1500 ((1-0)/1500) then, the time for the rest of the fade animation can be calculated in the same way ((1-0.25)/1500). This will be your duration of the animation for the resume part. The formula is ((finalValue - currentValue)/totalTime). Current value for each animation will be the value stored in listeners.

Now when the button is pressed again, you will calculate time remaining for the each animation values as described above and will start the animation sequence again with durations calculated above.If animateUp had completed and fadeValue was running, duration for animateUp using the formula will be 0. You will call the animation sequence with updated durations.

Once the sequence has completed, you can restart the sequence by resetting the current listener values of all the animations so that the durations are recalculated and all animation durations reset back to original values

restartAnimation() {
  this.animateUpValue = 0; //initialvalue
  this.fadeValue = 0; //initialvalue
  ...

  this.state.animateUp.setValue(0); //initialValue
  this.state.fadeValue.setValue(0); //initialValue
  ...
}

Let me know if you have any problems understanding.

Upvotes: 3

Related Questions