Animations are very important for the user experience, so almost every application is required. React Native provides 2 animations systems: Animated
and LayoutAnimation
but today I will just introduce you to Animated.
Animated
The Animated API is designed to accurately represent animations with very effective interactions. Animated focuses on the declared relationship between input and output, using start
/ stop
methods to control time-based animation execution.
Animated
has 6 types of animatable components: View
, Text
, Image
, ScrollView
, FlatList
and SectionList
, but you can also create your own using Animated.createAnimatedComponent()
.
There are 3 main methods that you can use to create animations:
- Animated.timing () : Mapping with time range to easing value
- Animated.decay () : Start with an initial velocity and gradually stop
- Animated.spring () : Provides a basic spring physical model
Along with the Animated methods above, there are composing methods to combine animations in complex ways:
- Animated. parallel () : Perform animations at the same time
- Animated.sequence () : Performs the animation sequentially
- Animated.stagger () : Perform animations with a combination of sequential and parallel
Animated.timing ()
The first animation we will create is a spinning animation using Animated.timing () .
1 2 3 4 5 6 7 8 9 10 11 | // Example implementation: Animated.timing( someValue, { toValue: number, duration: number, easing: easingFunction, delay: number } ) |
To create the animation above, we first need to import Animated , Image , and Easing from react-native
.
1 2 3 4 5 6 7 8 9 10 | import { AppRegistry, StyleSheet, Text, View, Animated, Image, Easing } from 'react-native' |
Easing is a module that allows us to use methods for easing such as linear, ease, quad, cubic, sin, elastic, bounce, back, bezier, in, out, inout …
First we need to initialize an animated value for the spinning value, we will set the value in the constructor:
1 2 3 4 5 | constructor () { super() this.spinValue = new Animated.Value(0) } |
Next, we will create a spin method to perform the spinning animation and call it at componentDidMount to execute right after opening the screen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | componentDidMount () { this.spin() } spin () { this.spinValue.setValue(0) Animated.timing( this.spinValue, { toValue: 1, duration: 4000, easing: Easing.linear } ).start(() => this.spin()) } |
The spin () function will call the Animated.timing function to execute the animation from value 0 -> 1, with a duration of 4 seconds. The Animated.timing function needs to pass a value and a config object, the config object can get toValue, duration, easing, delay. We call the start () function and pass the spin callback () which will be called as soon as the animation completes.
Once we have the methods we will need to render the animations in the UI:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | render () { const spin = this.spinValue.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'] }) return ( <View style={styles.container}> <Animated.Image style={{ width: 227, height: 200, transform: [{rotate: spin}] }} source={{uri: 'https://example.com/example.png'}} /> </View> ) } |
Above we create a spin variable and use the interpolate function, this is the function that helps us map the value from 0 -> 1, the output will be from 0 degrees -> 360 degrees. In styles of Animated.Image we have added the transfrom property and attached the spin value to the rotate property
1 2 | transform: [{rotate: spin}] |
So we have done an animation already!
Animated.allel ()
Animated. parallel () will execute an array of animation at the same time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // API Animated.parallel(arrayOfAnimations) // In use: Animated.parallel([ Animated.spring( animatedValue, { //config options } ), Animated.timing( animatedValue2, { //config options } ) ]) |
To create the animation as shown with Animated.allel, we will first create 3 animated values in the constructor:
1 2 3 4 5 6 7 | constructor () { super() this.animatedValue1 = new Animated.Value(0) this.animatedValue2 = new Animated.Value(0) this.animatedValue3 = new Animated.Value(0) } |
Next, we will create a method to execute the animation and call it at componentDidMount
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | componentDidMount () { this.animate() } animate () { this.animatedValue1.setValue(0) this.animatedValue2.setValue(0) this.animatedValue3.setValue(0) Animated.parallel([ this.createAnimation(this.animatedValue1, 2000, Easing.ease), this.createAnimation(this.animatedValue2, 1000, Easing.ease, 1000), this.createAnimation(this.animatedValue3, 1000, Easing.ease, 2000) ]).start() } createAnimation = (value, duration, easing, delay = 0) => { return Animated.timing( value, { toValue: 1, duration, easing, delay } ) } |
In the render method we will create the interpolate value:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | render () { const scaleText = this.animatedValue1.interpolate({ inputRange: [0, 1], outputRange: [0.5, 2] }) const spinText = this.animatedValue2.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '720deg'] }) const introButton = this.animatedValue3.interpolate({ inputRange: [0, 1], outputRange: [-100, 400] }) ... } |
Finally, we will render the Animated.View:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <View style={[styles.container]}> <Animated.View style={{ transform: [{scale: scaleText}] }}> <Text>Welcome</Text> </Animated.View> <Animated.View style={{ marginTop: 20, transform: [{rotate: spinText}] }}> <Text style={{fontSize: 20}}> to the App! </Text> </Animated.View> <Animated.View style={{top: introButton, position: 'absolute'}}> <TouchableHighlight onPress={this.animate.bind(this)} style={styles.button}> <Text style={{color: 'white', fontSize: 20}}> Click Here To Start </Text> </TouchableHighlight> </Animated.View> </View> |
We use scaleText to scale the first View, spinText to rotate the second View, and the introButton to change the marginTop of the 3rd View. When the animate () function is called, all of this animation will be done at once.
Conclude
In this article, I only showed you about Animated.timing () for single animation implementation and Animated. parallel () to combine the animation implementation. You can refer to at:
https://reactnative.dev/docs/animated
https://reactnative.dev/docs/animations
https://medium.com/react-native-training/react-native-animations-using-the-animated-api-ebe8e0669fae