[React Native] Animation

2021. 1. 4. 01:05React/React Native

1. XY Animation

1) 기본

import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import AnimOne from './src/Animation01'

class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <AnimOne/>
      </View>
    )
  }
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FFF'
  }
});

export default App;
import React, { Component } from 'react';
import { View, Text, StyleSheet, Animated } from 'react-native';

class AnimOne extends Component {

    constructor() {
        super();
        this.mySquare = new Animated.ValueXY(0, 0);
    }

    componentDidMount() { 
        Animated.spring(this.mySquare, {
            toValue: {x:50, y: 300}
        }).start();
    }

    render() {
        return (
            <Animated.View 
                style={this.mySquare.getLayout()}
                // style={{
                //     left: this.mySquare.x,
                //     top: this.mySquare.y
                // }}
            >
                <View style={styles.square}>
                </View>
            </Animated.View>
            )
    }
};

const styles = StyleSheet.create({
    square: {
        width: 100,
        height: 100,
        backgroundColor: 'skyblue'
    }
});

export default AnimOne;
코드 설명
componentDidMount() render 함수 이후 가장 나중에 실행되는 함수

2) 응용

다양한 효과는 공식 문서(reactnative.dev/docs/animated#configuring-animations)에서 확인할 수 있다.

import { View, Text, StyleSheet, Animated, Easing } from 'react-native';

...

    componentDidMount() {
        Animated.timing(this.mySquare, {
            toValue: {x:50, y: 300},
            duration: 2000, // 2초 
            delay: 1500, // 1.5 초
            easing: Easing.bounce
        }).start();
    }
    
...

3) 버튼

버튼을 클릭했을 때, 애니매이션이 동작하도록 설정할 수 있다.

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

class AnimOne extends Component {

    constructor() {
        super();
        this.state = {
            mySquare: new Animated.ValueXY(0, 0)
        }
    }

    runAnimation = () => {
        Animated.timing(this.state.mySquare, {
            toValue: {x:50, y: 300},
            duration: 2000, // 2초 
            delay: 1500, // 1.5 초
            easing: Easing.bounce
        }).start();
    }

    render() {
        return (
            <View>
                <Animated.View 
                    style={this.state.mySquare.getLayout()}
                >
                    <View style={styles.square}>
                    </View>
                </Animated.View>

                <Button
                    title="Animation Start"
                    onPress={this.runAnimation}
                />
            </View>
        )
    }
};

const styles = StyleSheet.create({
    square: {
        width: 100,
        height: 100,
        backgroundColor: 'skyblue'
    }
});

export default AnimOne;

 

 

 

2. 그 외 Animation

1) 투명도

투명도는 0(투명)에서 1(불투명)의 값을 가진다. 투명해지는 소스는 다음과 같다.

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

class AnimOne extends Component {

    constructor() {
        super();
        this.state = {
            mySquare: new Animated.Value(1)
        }
    }

    runAnimation = () => {
        Animated.timing(this.state.mySquare, {
            toValue: 0,
            duration: 2000, // 2초 
            delay: 1500, // 1.5 초
        }).start();
    }

    render() {
        return (
            <View>
                <Animated.View 
                    // style={this.state.mySquare.getLayout()}
                    style={{
                        opacity: this.state.mySquare
                    }}
                >
                    <View style={styles.square}>
                    </View>
                </Animated.View>

                <Button
                    title="Animation Start"
                    onPress={this.runAnimation}
                />
            </View>
        )
    }
};

const styles = StyleSheet.create({
    square: {
        width: 100,
        height: 100,
        backgroundColor: 'skyblue'
    }
});

export default AnimOne;

2) Interpolation

XY 애니매이션과 투명 효과를 동시에 적용하는 방법은 다음과 같다. 단, 주의해야할 점으로는 inputRange의 값은 반드시 작은 수에서 큰 수 순서대로 작성이 되어야하며, outputRange는 inputRange의 배열에 맞게 작성되어야한다.

 

예를 들어 위에서 아래로 이동하면서 투명해지는 효과의 경우, 투명도가 1 일 때 y 축 좌표가 0이여야하며,  투명도가 0 일 때 y축 좌표가 700이여야 한다.

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

class AnimOne extends Component {

    constructor() {
        super();
        this.state = {
            mySquare: new Animated.Value(1)
        }
    }

    runAnimation = () => {
        Animated.timing(this.state.mySquare, {
            toValue: 0,
            duration: 2000, // 2초 
            delay: 1500, // 1.5 초
        }).start();
    }

    render() {
        return (
            <View>
                <Animated.View 
                    // style={this.state.mySquare.getLayout()}
                    style={{
                        opacity: this.state.mySquare,
                        top: this.state.mySquare.interpolate({
                            inputRange: [0, 1], // 투명도 효과
                            outputRange: [700, 0] // 동시 효과
                        })
                    }}
                >
                    <View style={styles.square}>
                    </View>
                </Animated.View>

                <Button
                    title="Animation Start"
                    onPress={this.runAnimation}
                />
            </View>
        )
    }
};

const styles = StyleSheet.create({
    square: {
        width: 100,
        height: 100,
        backgroundColor: 'skyblue'
    }
});

export default AnimOne;

그리고, style에서 top 속성이 아닌 transform 속성을 통해 부여가 가능하다.

...
             <Animated.View 
                    style={{
                        opacity: this.state.mySquare,
                        transform: [{
                            translateY: this.state.mySquare.interpolate({
                                inputRange: [0, 1], // 투명도 효과 
                                outputRange: [700, 0] // 동시 효과
                            })
                        }]
                    }}
                >
                    <View style={styles.square}>
                    </View>
                </Animated.View>
...

3) Interpolation 응용

도형이 회전하는 효과와 텍스트 효과는 다음과 같다.

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

class AnimOne extends Component {

    constructor() {
        super();
        this.state = {
            mySquare: new Animated.Value(1)
        }
    }

    runAnimation = () => {
        Animated.timing(this.state.mySquare, {
            toValue: 0,
            duration: 2000, // 2초 
            delay: 1500, // 1.5 초
        }).start();
    }

    render() {
        return (
            <View>
                <Animated.View 
                    // style={this.state.mySquare.getLayout()}
                    style={{
                        opacity: this.state.mySquare,
                        transform: [
                            {
                                rotateX: this.state.mySquare.interpolate({
                                    inputRange: [0, 0.5, 1], // 투명도 효과 
                                    outputRange: ['0deg', '180deg', '360deg'] // 동시 효과
                                })
                            },
                            {
                                translateX: this.state.mySquare.interpolate({
                                    inputRange: [0, 0.5, 1], // 투명도 효과 
                                    outputRange: [300, 150, 0] // 동시 효과
                                })
                            }
                        ]
                    }}
                >
                    <View style={styles.square}>
                    </View>
                </Animated.View>

                <Animated.Text
                    style={{
                        fontSize: this.state.mySquare.interpolate({
                            inputRange: [0, 0.5, 1], // 투명도 효과 
                            outputRange: [40, 30, 20] // 동시 효과
                        }),
                        color: this.state.mySquare.interpolate({
                            inputRange: [0, 0.5, 1],
                            outputRange: ['red', 'green', 'blue']
                        })
                    }}
                >
                    <Text>Animated Text</Text>
                </Animated.Text>

                <Button
                    title="Animation Start"
                    onPress={this.runAnimation}
                />
            </View>
        )
    }
};

const styles = StyleSheet.create({
    square: {
        width: 100,
        height: 100,
        backgroundColor: 'skyblue'
    }
});

export default AnimOne;

4) 효과 순서 설정

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

class AnimTwo extends Component {

    constructor() {
        super();
        this.state = {
            redSquare: new Animated.Value(1),
            greenSquare: new Animated.ValueXY(0, 0),
            blueSquare: new Animated.ValueXY(0, 0)
        }
    }

    runAnimation = () => {
        Animated.sequence([ // 순서
            Animated.timing(this.state.redSquare, {
                toValue: 0
            }),

            Animated.parallel([ // 동시 적용 효과
                Animated.spring(this.state.greenSquare, {
                    toValue: {x: 200, y: 0}
                }),
                Animated.spring(this.state.blueSquare, {
                    toValue: {x: 200, y: 400}
                })
            ])
        ]).start();
    }

    render() {
        return (
            <View>
                <Animated.View
                    style={{
                        opacity: this.state.redSquare
                    }}
                >
                    <View style={styles.redSquare}>
                    </View>
                </Animated.View>

                <Animated.View
                    style={this.state.greenSquare.getLayout()}
                >
                    <View style={styles.greenSquare}>
                    </View>
                </Animated.View>

                <Animated.View
                    style={this.state.blueSquare.getLayout()}
                >
                    <View style={styles.blueSquare}>
                    </View>
                </Animated.View>

                <Button
                    title="Animation Start"
                    onPress={this.runAnimation}
                />
            </View>
        )
    }
};

const styles = StyleSheet.create({
    redSquare: {
        width: 100,
        height: 100,
        backgroundColor: 'red'
    },
    greenSquare: {
        width: 100,
        height: 100,
        backgroundColor: 'green'
    },
    blueSquare: {
        width: 100,
        height: 100,
        backgroundColor: 'blue'
    },
});

export default AnimTwo;

 

728x90

'React > React Native' 카테고리의 다른 글

[React Native] 재사용 가능한 Component  (0) 2021.01.04
[React Native] Debugger  (0) 2021.01.04
[React Native] 연락처 접근  (0) 2021.01.02
[React Native] Image Picker  (1) 2020.12.31