Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3D Animations on View with React Native

I want to implement a flip effect in my React Native app, similar like described here:

https://www.codementor.io/reactjs/tutorial/building-a-flipper-using-react-js-and-less-css

My question is. Can I achieve it somehow with the help of some library like 'Animations' https://facebook.github.io/react-native/docs/animations.html or I have to play with 'plain' CSS styles.

What is the 'good practive' for such animations in React Native?

class CardBack extends Component {
  render() {
    return (
      <TouchableOpacity onPress={this.flip}>
        <View style={styles.scrumCardBorder}>
          <View style={styles.cardBack}>
          </View>
        </View>
      </TouchableOpacity>
    );
  }

  flip() {
    this.setState({flipped: !this.state.flipped})
  }
}

class CardFront extends Component {
  render() {
    return (
      <TouchableOpacity>
        <View style={styles.scrumCardBorder}>
          <View style={styles.cardFront}>
            <Text style={styles.cardValue}>5</Text>
          </View>
        </View>
      </TouchableOpacity>
    );
  }
}
like image 613
Łukasz Rzeszotarski Avatar asked Oct 31 '22 14:10

Łukasz Rzeszotarski


2 Answers

We can use transform and Interpolate to make 3D rotate Animation.

class RotateAnimation extends React.Component {
  _rotateValue = new Animated.Value(0);
  startAnimated = () => {
    Animated.timing(this._rotateValue, {
      toValue: 360,
      duration: 800, 
      useNativeDriver: true 
    }).start()
  }

  getTransform = () => {
    const rotate = this._rotateValue.interpolate({
      inputRange: [0, 180, 360], 
      outputRange: ['0deg', '180deg', '360deg'], 
      extrapolate: 'clamp',
    }) 
    if (this.props.horizontal) {
      return {
        transform: {
          perspective: WINDOW_WIDTH, 
          rotateX: rotate
        }
      }
    }

    return {
      transform: {
        perspective: WINDOW_WIDTH, 
        rotateY: rotate
      }
    }
  }

  render() {
    return  (<Animated.View style={[style, ]} />
      {this.props.children}
    </Animated.View>)
  }
}

If you want to use transform around a certain point. Can try this.

like image 94
RY_ Zheng Avatar answered Nov 09 '22 03:11

RY_ Zheng


Use Animated api for these transformations.

enter image description here

Note: Rotation along the axis(ie, rotateX or rotateY) with perspective will give you the feel of flipping.

Always use useNativeDriver: true for better performance.

Example code:

import React, {Component} from 'react';
import {View, Animated, StyleSheet, Button} from 'react-native';

export default class Container extends Component {
  constructor() {
    super();
    this.animation = new Animated.ValueXY({x: 0, y: 0});
    const inputRange = [0, 1];
    const outputRange = ['0deg', '180deg'];
    this.rotateX = this.animation.x.interpolate({inputRange, outputRange});
    this.rotateY = this.animation.y.interpolate({inputRange, outputRange});
  }
  flip = (val) => {
    this.animation[val].setValue(0);
    Animated.timing(this.animation[val], {
      toValue: 1,
      duration: 500,
      useNativeDriver: true,
    }).start();
  };
  render() {
    const {rotateX, rotateY} = this;
    return (
      <View style={styles.container}>
        <Animated.View
          style={{
            ...styles.item,
            transform: [{rotateX}, {rotateY}, {perspective: 500}],
          }}
        />
        <Button title="flip x " onPress={() => this.flip('x')} />
        <Button title="flip y " onPress={() => this.flip('y')} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {flex: 1, alignItems: 'center', justifyContent: 'center'},
  item: {
    height: 200,
    width: 200,
    backgroundColor: 'red',
    marginBottom: 20,
  },
});
like image 26
Aswin C Avatar answered Nov 09 '22 04:11

Aswin C