online software programming courses

React native advanced 3D animation in a loop

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.

 

1. How to use state variables for animation controls

2. How to use simple rotation functions to make advanced animation and give 3D effect

3. How to use componentDidMount() and parallel() functions to run animation in an infinite loop.

4. How to reset animation using start() callback function. 

5. How to use Ease.linear for function for realistic animation. 

6. Overlapping Animated views to created 3D perspective.

 

1. How to use state variables for animation controls

    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.

 

2. How to use simple rotation functions to make advanced animation and give a 3D 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.

 

3. How to use componentDidMount() and parallel() functions to run animation in an infinite loop

    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()

  1. It starts all the defined animation together.
  2. It stops all the animation together when one of them is stopped.

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.

Watch the 3D animation video on youtube

 

4. How to reset animation using start() callback function. 

    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();
        });

 

5. How to use Ease.linear for function for realistic animation. 

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

 

6. Overlapping Animated views to created 3D perspective.

<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