Introduction
Animations enable you to depict physically believable motion in your interface. Animations are critical for a great user experience.
React Native has two animation systems: Animated and LayoutAnimation. Animated allows for detailed and interactive modification of particular values, while LayoutAnimation allows for animated global layout transactions.
Click on the following link to read further: Hooks in React JS
Animated API
The Animated API represents a wide range of fascinating animation and interaction patterns in a clear and performant manner. Animated emphasizes direct relationships between inputs and outputs and adjustable transforms and start/stop methods for controlling time-based animation execution.
Animated exports six types of animatable components:
- View
- Text
- Image
- ScrollView
- FlatList
- SectionList
However, you can also make your own using Animated.createAnimatedComponent().
Configuring Animation
There are three types of animation available in Animated. Each animation type has its animation curve that determines how your values animate from their initial value to their final value:
- Animated. timing(): The value is animated along a timed easing curve.
- Animated. spring(): Animates following the analytical spring model based on damped harmonic oscillation.
- Animated.decay(): Based on a decay coefficient, it animates a value from an initial velocity to zero.
Working with Animations
The following steps can be taken to implement animations in React Native:
- Import the animation modules.
- Declare an animated value.
- Define how the animated value changes over time.
- Set the animated style for the component and render an animated version of it.
- Start the animation.
Start animations by executing start() on your animation. start() accepts a completion callback that will be triggered when the animation is finished. If the animation is typically completed, then the completion callback will be called with the parameter {finished: true}. If stop() were called on the animation before it could finish (for example, because a gesture or another animation halted it), it would receive {finished: false}.
Animated.timing({}).start(({ finished }) => {
/* completion callback */
});
Composing Animation
Composition functions can be used to combine animations in complex ways:
- Animated.delay() : animation starts after a given delay.
- Animated. parallel(): number of animations start at the same time.
- Animated. sequence(): starts the animations one by one, waiting for each one to finish before moving on to the next.
- Animated. stagger(): this starts animations in order and parallel, but with a delay between them.
Animated.sequence([
// decay, then spring to start and twirl
Animated.decay(position, {
velocity: { x: gestureState.vx, y: gestureState.vy }, // velocity from gesture release
deceleration: 0.997
}),
Animated.parallel([
// after decay, in parallel:
Animated.spring(position, {
toValue: { x: 0, y: 0 } // return to start
}),
Animated.timing(twirl, {
// and twirl
toValue: 360
})
])
]).start(); // starting the sequence group
Combining Animated Values
You can make a new animated value by adding, subtracting, multiplying, dividing, or moduloing two animated values:
- Animated.add()
- Animated.subtract()
- Animated.divide()
- Animated.modulo()
- Animated.multiply()
//An example, inverting a scale (2x --> 0.5x)
const a = new Animated.Value(1);
const b = Animated.divide(1, a);
Animated.spring(a, {
toValue: 2
}).start();
Interpolation
The interpolate() method lets you map different input ranges to different output ranges. By default, it will extrapolate the curve beyond the supplied fields, but you may also clamp the output value. By default, it employs linear interpolation but also allows easing functions.
//to convert a 0-1 range to a 0-100 range
value.interpolate({
inputRange: [0, 1],
outputRange: [0, 100]
});
Also see, React Native Reanimated
Handling gestures and other events
Animated. event() can map gestures like panning and scrolling, as well as other events, to animated values. This is accomplished by using a structured map syntax, which allows values to be extracted from complex event objects.
Example
The view in the following example will fade in and out based on the animated variable animFade. The opacity of the view will change to 1 in 5 seconds and back to 0 in 1 second on clicking the "Fade in View" and "Fade out View" buttons, respectively.
import React, { Component } from "react";
import { Animated, Text, View, StyleSheet, Button, SafeAreaView } from "react-native";
class App extends Component {
// animFade will be used as the value for opacity. Initial Value: 0
state = {
animFade: new Animated.Value(0)
};
fadeIn = () => {
Animated.timing(this.state.fadeAnim, {
toValue: 1,
duration: 5000
}).start();
};
fadeOut = () => {
Animated.timing(this.state.fadeAnim, {
toValue: 0,
duration: 1000
}).start();
};
render() {
return (
<SafeAreaView style={styles.container}>
<Animated.View
style={[
styles.fadingContainer,
{
// Bind opacity to animated value
opacity: this.state.animFade
}
]}
>
<Text style={styles.fadingText}>Fading View!</Text>
</Animated.View>
<View style={styles.buttonRow}>
<Button title="Fade In View" onPress={this.fadeIn} />
<Button title="Fade Out View" onPress={this.fadeOut} />
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center"
},
fadingContainer: {
padding: 20,
backgroundColor: "powderblue"
},
fadingText: {
fontSize: 28
},
buttonRow: {
flexBasis: 100,
justifyContent: "space-evenly",
marginVertical: 16
}
});
export default App;