This post was originally posted on my blog @ isaks.io In this tutorial, I’ll show you how to create a button that rotates 720 degrees when it’s pressed. We will be using the React Native Animated animation system to create the rotation animation.
Photo by Kinson Leung on Unsplash
Creating the component
First, we create the functional component ButtonWithSpin
that has a TouchableOpacity
component with some text inside.
return (
<TouchableOpacity
onPress={async () => handleAnimation()}
style={{ width: 60 }}
>
<Animated.Text style={animatedStyle}>Click me</Animated.Text>
</TouchableOpacity>
);
Notice that the text is created using the Animated.Text
component. This is because the text that is going to rotate has to be animatable. If you are rotating something else, then you can use any of these components as well:
- Animated.Image
- Animated.ScrollView
- Animated.View
- Animated.Text
- Animated.FlatList
- Animated.SectionList
We also use the useState
Hook to store our rotateAnimation
value. This is an animation value from the Animated library. We use new Animated.Value(0)
to initialize the value.
The handleAnimation function
const handleAnimation = () => {
Animated.timing(rotateAnimation, {
toValue: 1,
duration: 800,
}).start(() => {
rotateAnimation.setValue(0);
});
};
Animated.timing()
animates a value over time using easing functions. By default, it uses the easeInOut
curve which is perfect for what we are making. We pass our rotateAnimation
value and a config value, where we set the duration to be 800ms. The animation is started by calling start()
, and we include a callback function that resets the animation.
Interpolate
The interpolate()
method maps input ranges to output ranges. A basic mapping to convert a 0–1 range to a 0–100 range would be:
value.interpolate({
inputRange: [0, 1],
outputRange: [0, 100],
});
You can also use the interpolate()
method to map out strings. Since we want to rotate our text from 0 degrees to 720 degrees, our code will look like this:
const interpolateRotating = rotateAnimation.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "720deg"],
});
const animatedStyle = {
transform: [
{
rotate: interpolateRotating,
},
],
};
We also created the animatedStyle
object, which includes an array transform
with the rotate value interpolateRotating
that we just created.
Putting everything together
Add the animtedStyle
object to the Animated.Text
component and a width
to the TouchableOpacity
component and we are done!
This is what the end product looks like:
Button spinning after click
And the code:
import React, { useState } from "react";
import { TouchableOpacity, Animated } from "react-native";
const ButtonWithSpin = () => {
const [rotateAnimation, setRotateAnimation] = useState(new Animated.Value(0));
const handleAnimation = () => {
Animated.timing(rotateAnimation, {
toValue: 1,
duration: 800,
}).start(() => {
rotateAnimation.setValue(0);
});
};
const interpolateRotating = rotateAnimation.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "720deg"],
});
const animatedStyle = {
transform: [
{
rotate: interpolateRotating,
},
],
};
return (
<TouchableOpacity
onPress={async () => handleAnimation()}
style={{ width: 60 }}
>
<Animated.Text style={animatedStyle}>Click me</Animated.Text>
</TouchableOpacity>
);
};
export default ButtonWithSpin;
And there we have it. I hope you have found this useful. This was my first post on Medium, so any feedback is greatly appreciated!