Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

React Native 애니메이션 완벽 가이드: Animated API와 LayoutAnimation 활용법

React Native 애니메이션 개요

React Native는 기본적으로 Animated 컴포넌트를 제공하여 앱에 풍부한 인터랙티브 요소를 손쉽게 추가할 수 있습니다. 이 컴포넌트를 활용하면 View, Text, Image, ScrollView, FlatList, SectionList 등 주요 컴포넌트에 애니메이션 효과를 적용할 수 있습니다.

React Native가 제공하는 애니메이션은 크게 두 가지입니다.

  • Animated API
  • LayoutAnimation

1. Animated API

Animated API는 입력값과 출력값을 기반으로 시간의 흐름에 따라 애니메이션을 구현할 때 사용합니다. 아래 예제에서는 Animated.timing() 함수를 활용해 박스의 너비와 높이를 동적으로 변경해 보겠습니다.

애니메이션을 사용하려면 먼저 컴포넌트를 임포트해야 합니다.

import { Animated } from 'react-native'

Animated.timing() 함수는 이징(easing) 함수를 사용하며, 지정된 값이 시간에 따라 부드럽게 변화합니다. 기본 이징 함수는 easeInOut이며, 필요에 따라 다른 이징 함수를 사용하거나 직접 정의할 수도 있습니다.

Animated.timing() 함수의 기본 구조는 다음과 같습니다.

Animated.timing(animateparam, {
    toValue: 100,
    easing: easingfunc,
    duration: timeinseconds
}).start();

이번 예제에서는 View의 너비와 높이를 애니메이션할 것이므로, 먼저 애니메이션 값을 초기화합니다.

animatedWidthanimatedHeightcomponentWillMount에서 다음과 같이 초기화합니다.

componentWillMount = () => {
    this.animatedWidth = new Animated.Value(50)
    this.animatedHeight = new Animated.Value(100)
}
참고: componentWillMount는 현재 React에서 공식적으로 지원이 중단(deprecated)된 라이프사이클 메서드입니다. 최신 버전의 React Native에서는 constructor 또는 componentDidMount에서 초기화하는 방식을 권장합니다.

이후 Animated.timing 함수를 다음과 같이 추가합니다.

Animated.timing(this.animatedWidth, {
    toValue: 200,
    duration: 1000
}).start()
Animated.timing(this.animatedHeight, {
    toValue: 500,
    duration: 500
}).start()

애니메이션 동작 원리

TouchableOpacity 컴포넌트를 누르면 onPress 이벤트를 통해 this.animatedBox 함수가 호출되고, 이 함수 내부의 Animated.timing이 실행되면서 애니메이션이 시작됩니다. 즉, TouchableOpacity를 터치하면 View의 너비와 높이가 설정한 duration만큼의 시간에 걸쳐 부드럽게 변하게 됩니다.

전체 예제 코드

import React, { Component } from 'react'
import { View, StyleSheet, Animated, TouchableOpacity } from 'react-native'
class Animations extends Component {
    componentWillMount = () => {
        this.animatedWidth = new Animated.Value(50)
        this.animatedHeight = new Animated.Value(100)
    }
    animatedBox = () => {
        Animated.timing(this.animatedWidth, {
            toValue: 200,
            duration: 1000
        }).start()
        Animated.timing(this.animatedHeight, {
            toValue: 500,
            duration: 500
        }).start()
    }
    render() {
        const animatedStyle = { width: this.animatedWidth, height: this.animatedHeight }
        return (
            <TouchableOpacity style={styles.container} onPress={this.animatedBox}>
                <Animated.View style={[styles.box, animatedStyle]} />
            </TouchableOpacity>
        )
    }
}
export default Animations
const styles = StyleSheet.create({
    container: {
        padding: 100,
        justifyContent: 'center',
        alignItems: 'center'
    },
    box: {
        backgroundColor: 'gray',
        width: 50,
        height: 100
    }
})

실행 결과

다음은 iOS와 Android 기기에서 확인한 화면입니다.

React Native 애니메이션 완벽 가이드: Animated API와 LayoutAnimation 활용법

회색 사각형 박스를 터치하면 애니메이션이 실행되는 것을 확인할 수 있습니다.

React Native 애니메이션 완벽 가이드: Animated API와 LayoutAnimation 활용법

2. LayoutAnimation API

LayoutAnimation은 Animated API보다 더 많은 제어권을 제공하며, 다음 렌더링/레이아웃 사이클에서 뷰에 적용될 생성(create) 및 업데이트(update) 애니메이션을 전역적으로 설정할 수 있습니다.

LayoutAnimation을 사용하려면 다음과 같이 임포트합니다.

import { LayoutAnimation } from 'react-native';

예제: LayoutAnimation 사용하기

Android에서 LayoutAnimation이 정상적으로 작동하려면 다음 코드를 반드시 추가해야 합니다.

UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);

import React from 'react';
import {
    NativeModules,
    LayoutAnimation,
    Text,
    TouchableOpacity,
    StyleSheet,
    View,
} from 'react-native';

const { UIManager } = NativeModules;
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);

export default class App extends React.Component {
    state = {
        w: 50,
        h: 50,
    };
    animatecircle = () => {
        LayoutAnimation.spring();
        this.setState({ w: this.state.w + 10, h: this.state.h + 10 })
    }
    render() {
        return (
            <TouchableOpacity style={styles.container} onPress={this.animatecircle}>
                <View style={[styles.circle, { width: this.state.w, height: this.state.h }]} />
            </TouchableOpacity>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
    },
    circle: {
        width: 200,
        height: 200,
        borderRadius: '50%',
        backgroundColor: 'green',
    },
});

실행 결과

React Native 애니메이션 완벽 가이드: Animated API와 LayoutAnimation 활용법

초록색 원을 탭하면 LayoutAnimation.spring()에 의해 스프링 효과와 함께 원의 크기가 10px씩 점점 커지는 애니메이션을 확인할 수 있습니다.

React Native 애니메이션 완벽 가이드: Animated API와 LayoutAnimation 활용법