Pikaurd
Pikaurd

Reputation: 1124

Repeat animation with new animated api

React-native introduce new Animated API, I want to make a loop animation such as a bubble scale up then scale down and repeat that progress.

However I can not figure it out. I've tried write some code like below

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

}

but not works very well.

Any suggestion will be appreciate.

Upvotes: 51

Views: 45987

Answers (8)

Michael
Michael

Reputation: 2288

Here's another example for an infinite animation using hooks and iterations set to "infinity". Avoids the use of the recursion in previous answers which sometimes led to funky behaviour during e2e testing for us.

  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();
  }, []);

Upvotes: 1

Adam Pietrasiak
Adam Pietrasiak

Reputation: 13184

Not sure if it's hacky, but I use this:

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

It's creating spring animation that will never (technically, for a very very very long time) stop waving.

For most of my cases it was enough. Also it has great performance as it does not require any JS tread action ever during animation.

If eventually you'd like to stop it gracefully:

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

And it'll nicely 'slow down' until it stops.

Upvotes: 0

Miguel Cardenas
Miguel Cardenas

Reputation: 1263

Try something like this:

componentDidMount() {
    this.bootAnimation();
  }

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

Upvotes: 6

silyevsk
silyevsk

Reputation: 4566

There's now loop animation available:

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

Upvotes: 146

joshblour
joshblour

Reputation: 1034

improved version of @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();
    }
  });
}

Upvotes: 19

robinsonlam
robinsonlam

Reputation: 34

You can set another animation then call the animation again:

An example I did to fade text in and out:

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

Upvotes: 0

bcomerford
bcomerford

Reputation: 433

I use the sequence method to pass an array of animations to cycle and then repeat the function.

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

If I'm toggling that animation on it's own it will fade in/out, however I layer it on top of a base to mimic an active state or hotspot-style button

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

React Native Sequence Documentation

Upvotes: 40

xinthink
xinthink

Reputation: 1490

It seems that 'looping' is not supported by the Animated api for now.

I managed to do that by start the animation again when it finished.

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

enter image description here

Looking forward to a better solution...

Upvotes: 1

Related Questions