In this tutorial, you learn how to do 3d advanced animation using simple rotation and parallel function. We will some the knowledge from previous tutorials. If you don't know the basics you can go head and view previous videos.
See the end result of the animation.
We will cover how to use simple animations based on the below points.
state ={
rotateY: new Animated.Value(0),
rotateX: new Animated.Value(180),
}
We declared two state variables to keep the track of the for rotation. First one is to keep the track of y-axis and the second one is fo x-axis and values 0 and 180 degree respectively. We initiated them using react native Animated.Value() function since we would be animated the values through out the animation of 3D effect. Our ultimate target is getting the below effect.
rorate1={
transform:[
{rotateY:this.state.rotateY.interpolate({
inputRange:[0, 180],
outputRange:["180deg", "360deg"],
})},
{rotateX:this.state.rotateY.interpolate({
inputRange:[0, 180],
outputRange:["180deg", "360deg"],
})}
]
}
rorate2={
transform:[
{rotateX:this.state.rotateX.interpolate({
inputRange:[180, 360],
outputRange:["0deg", "360deg"],
})},
{rotateY:this.state.rotateX.interpolate({
inputRange:[180, 360],
outputRange:["0deg", "720deg"],
})}
]
}
In general, react-native does not have a 3D library. If you see the code carefully you will find that we used many interpolations of rotation with many variations. Since react-native does not have a 3D animation package or library, we created this 3D effect using different kinds of rotation values both on the x-axis and y-axis.
First one rotate1, rotates the circle both on y and x-axis. and the second one rotates on x and y-axis. The second rotate object rotate2 has a different input and output range than rotate1. This creates more realistic illusions of 3D effect. You can also see the output range is converted to string values through interpolate function.
animate(){
const y= Animated.timing(this.state.rotateY,{
toValue:180,
duration:5000,
useNativeDriver:true,
easing:Easing.linear,
})
const x= Animated.timing(this.state.rotateX,{
toValue:360,
duration:5000,
useNativeDriver:true,
easing:Easing.linear,
})
Animated.parallel([
y,
x
]).start(()=>{
this.state.rotateY.setValue(0),
this.state.rotateX.setValue(180),
this.animate();
});
}
componentDidMount(){
this.animate();
}
ComponentDidMount() method gets called automatically after the render() method has been called. And then we call animate() function inside this function which calls parallel event. Animated.parallel has a start() callback function which starts the animation. Start() function can take additional parameters. Animated.parallel starts several animations at the same time. In our case, they are x and y animations. Parallel() is one of the several methods defined in Animated API in react native. The most important things to remember about parallel()
Animated.timing(): The most commonly used animation type, which makes a value change with time according to a transition curve. We used useNativeDriver:true to get cool native effect.
state ={
rotateY: new Animated.Value(0),
rotateX: new Animated.Value(180),
}
We can reset an animation using the start() callback function. That means we need to reset the initial state of our animation. States are declared are rotateY and rotateX. Just calling this.animate() inside start() callback would not reset the animation. That's why reset them using the below code below. We did this.state.rotateY.setValue(0) and this.state.rotateX.setValue(180). setValue() is associated with Animated.Value() function. You can use setValue() to change the state variable value.
Animated.parallel([
y,
x
]).start(()=>{
this.state.rotateY.setValue(0),
this.state.rotateX.setValue(180),
this.animate();
});
easing:Easing.linear
After the animated values reach their target, they stop suddenly and restarts again, this stopping and restaring is very obvious. Even though our animation runs in a loop for infinity, but as a sudden stop, it does not look like a natural running of animation . This is where the Easing.linear comes to rescue us. Without this animation is not natural at all. The default value of easeing is easeInOut, but we changed it to linear.
<Animated.View style={[styles.rotate, this.rorate1]}>
</Animated.View>
<Animated.View style={[styles.rotate, this.rorate2]}>
</Animated.View>
Since react-native does not have a native 3D library for animations, you can work around this problem by superpositioning two views at the same position using absolute positioning. The above Animated.View component uses the same style objects for both views.
The complete is given below
import React, { Component } from 'react';
import {View, StyleSheet, Animated, Easing} from 'react-native';
export default class ComplexR extends Component {
state ={
rotateY: new Animated.Value(0),
rotateX: new Animated.Value(180),
}
animate(){
const y= Animated.timing(this.state.rotateY,{
toValue:180,
duration:5000,
useNativeDriver:true,
easing:Easing.linear,
})
const x= Animated.timing(this.state.rotateX,{
toValue:360,
duration:5000,
useNativeDriver:true,
easing:Easing.linear,
})
Animated.parallel([
y,
x
]).start(()=>{
this.state.rotateY.setValue(0),
this.state.rotateX.setValue(180),
this.animate();
});
}
componentDidMount(){
this.animate();
}
rorate1={
transform:[
{rotateY:this.state.rotateY.interpolate({
inputRange:[0, 180],
outputRange:["180deg", "360deg"],
})},
{rotateX:this.state.rotateY.interpolate({
inputRange:[0, 180],
outputRange:["180deg", "360deg"],
})}
]
}
rorate2={
transform:[
{rotateX:this.state.rotateX.interpolate({
inputRange:[180, 360],
outputRange:["0deg", "360deg"],
})},
{rotateY:this.state.rotateX.interpolate({
inputRange:[180, 360],
outputRange:["0deg", "720deg"],
})}
]
}
render(){
return (
<View style={styles.container}>
<Animated.View style={[styles.rotate, this.rorate1]}>
</Animated.View>
<Animated.View style={[styles.rotate, this.rorate2]}>
</Animated.View>
</View>
);
}
}
const styles=StyleSheet.create({
container:{
flex:1,
justifyContent:"center",
alignItems:"center",
},
rotate:{
position:"absolute",
top:250,
left:160,
width:100,
height:100,
backgroundColor:"#33ccff",
borderRadius:50,
borderColor:"#6A6C6E",
borderWidth:5,
}
});
Build a mobile app with Laravel Backend