Creating an Asynchronous Loading Image Component in React Native — Part II
We add animations to the placeholder in the 2nd part of our series building an asynchronous image component in React Native.
Adding animations to UI changes is a nice touch that provides a better experience for users and React Native’s Animated API makes animations simpler than ever. 😎
In part 2 of this series you will add an explode animation for the transition of the placeholder leaving the view and the image entering after it loads from the network.
Previous
Skip to the Source
Preparing for the Animation
To achieve the explode effect we will need to animate the opacity of the placeholder and image along with the placeholder’s scale. Animating these styles allows us to use the useNativeDriver option in our animations, releasing the JS thread for other tasks.
We will also be making the placeholder an Animated.View and the image an Animated.Image so that they support the animated styles.
constructor(props: Props) {
super(props)
this.state = {
loaded: false,
imageOpacity: new Animated.Value(0.0),
placeholderOpacity: new Animated.Value(1.0),
placeholderScale: new Animated.Value(1.0)
}
}render() {
const {
placeholderColor,
style,
source
} = this.props const {
imageOpacity,
loaded,
placeholderOpacity,
placeholderScale
} = this.state return (
<View
style={style}> <Animated.Image
source={source}
resizeMode={'contain'}
style={[
style,
{
opacity: imageOpacity,
position: 'absolute',
resizeMode: 'contain'
}
]}
onLoad={this._onLoad} /> {!loaded &&
<Animated.View
style={[
style,
{
backgroundColor: placeholderColor,
opacity: placeholderOpacity,
position: 'absolute',
transform: [{ scale: placeholderScale }]
}
]} />
}
</View>
)
}
Creating the Animation
The animation consists of two animation sequences to achieve it’s appearance. We first make it appear that the placeholder implodes then blasts out when the image loads. 💣 💥
For the implosion we shrink the placeholder’s scale and begin lowering it’s opacity. Then for the explosion we grow those properties while running a parallel animation increasing the image’s opacity. Animated makes it easy!
_onLoad = () => {
const {
placeholderScale,
placeholderOpacity,
imageOpacity
} = this.state Animated.sequence([
//
// Implode
//
Animated.parallel([
Animated.timing(placeholderScale, {
toValue: 0.7,
duration: 100,
useNativeDriver: true
}),
Animated.timing(placeholderOpacity, {
toValue: 0.66,
duration: 100,
useNativeDriver: true
}),
]),
//
// Explode
//
Animated.parallel([
Animated.parallel([
Animated.timing(placeholderOpacity, {
toValue: 0,
duration: 200,
useNativeDriver: true
}),
Animated.timing(placeholderScale, {
toValue: 1.2,
duration: 200,
useNativeDriver: true
}),
]),
Animated.timing(imageOpacity, {
toValue: 1.0,
delay: 200,
duration: 300,
useNativeDriver: true
})
])
]).start(() => {
this.setState(() => ({ loaded: true }))
})
}
Next Steps
In the rest of this series we’ll make this component look even better.
Thanks for reading! We look forward to sharing more with this series and feel free to ask any questions below. 🚀
Did you know we curate the best resources on React Native and related frameworks just for you each week? Subscribe to our weekly React Native Newsletter to get it in your inbox each week. 🙌🏻