
Animated 라이브러리는 애니메이션을 부드럽고 강력하며 쉽게 제작하고 유지할 수 있도록 설계되었다. Animated는 입력과 출력 간의 선언적으로 관계, 그 사이의 구성 가능한 변환, 시간 기반 애니메이션 실행을 제어하는 시작/중지 메서드에 중점을 둔다.
애니메이션을 생성하는 기본 워크플로우는 Animated.Value를 생성하고 이를 애니메이션 컴포너틑의 하나 이상의 스타일 속성에 연결한 후 Animated.timing()을 사용하여 애니메이션을 통해 업데이트를 구동하는 것이다.
애니메이션 값을 직접 수정하지 않아야 한다. useRef 훅을 사용하여 변경 가능한 참고 객체를 반환할 수 있다. 이 참조 객체의 current 속성은 지정된 인수로 초기화되고 컴포넌트 라이프사이클 동안 유지된다.
fadeAnim이라는 애니메이션 값을 기반으로 페이드 인 및 페이드 아웃하는 View가 포함되어 있다.
import React, {useRef} from 'react';
import {
Animated,
Text,
View,
StyleSheet,
Button,
SafeAreaView,
} from 'react-native';
const App = () => {
// fadeAnim은 불투명도(opacity)를 위한 값으로 사용됩니다. 초기 값: 0
const fadeAnim = useRef(new Animated.Value(0)).current;
const fadeIn = () => {
// fadeAnim 값을 5초 안에 1로 변경합니다
Animated.timing(fadeAnim, {
toValue: 1,
duration: 5000,
useNativeDriver: true,
}).start();
};
const fadeOut = () => {
// fadeAnim 값을 3초 안에 0으로 변경합니다
Animated.timing(fadeAnim, {
toValue: 0,
duration: 3000,
useNativeDriver: true,
}).start();
};
return (
<SafeAreaView style={styles.container}>
<Animated.View
style={[
styles.fadingContainer,
{
// 불투명도를 애니메이션 값에 바인딩
opacity: fadeAnim,
},
]}>
<Text style={styles.fadingText}>Fading View!</Text>
</Animated.View>
<View style={styles.buttonRow}>
<Button title="Fade In View" onPress={fadeIn} />
<Button title="Fade Out View" onPress={fadeOut} />
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
fadingContainer: {
padding: 20,
backgroundColor: 'powderblue',
},
fadingText: {
fontSize: 28,
},
buttonRow: {
flexBasis: 100,
justifyContent: 'space-evenly',
marginVertical: 16,
},
});
export default App;
자세한 사항은 애니메이션 가이드에서 Animated를 사용한 추가 예제를 참조하자.
Animated에서는 사용할 수 있는 두 가지 값 유형이 있다.
Animated.Value(): 단일 값Animated.ValueXY(): 벡터 값Animated.Value는 스타일 속성 또는 기타 props에 바인딩될 수 있으며 보간(interpolation)될 수 있다.
단일 Animated.Value는 여러 속성을 수동할 수 있다.
보간이란 알려진 데이터 점 집합의 범위 내에 새 데이터 점을 추가하는 기법을 말한다. 보간을 사용하여 누락된 데이터를 채우고, 기존 데이터를 평활화하고, 예측 등을 수행할 수 있다.
Animated는 세 가지 애니메이션 유형을 제공한다. 각 애니메이션 유형은 초기 값에서 최종 값으로 애니메이션화하는 동안 애니메이션 곡선을 제공한다.
Animated.decay(): 초기 속도로 시작하여 점차 정지한다.Animated.spring() : 기본적인 스프링 물리 모델을 제공한다.Animated.timing() : 완화(easing) 함수로 값을 시간에 따라 애니메이션화한다.대부분의 경우 timing()을 사용하는 경우가 많다. 기본적으로, 이 함수는 대칭 easeInOut 곡선을 사용하여 객체가 최대 속도까지 점진적으로 가속되어 정지하기 전 점진적으로 감속하는 것을 표현한다.
애니메이션은 start()를 호출하여 시작된다. start()는 애니메이션이 완료되었을 때 호출되는 완료 콜백을 받는다. 애니메이션이 정상적으로 종료되면 콜백은 {finished: true}와 함께 호출된다. 애니메이션이 중단되거나 중지(stop())된 경우에는 {finished: false}가 전달된다.
Animated.timing({}).start(({finished}) => {
/* 완료 콜백 */
});
네이티브 드라이버를 사용하면 애니메이션에 대한 모든 것을 애니메이션 시작 전에 네이티브로 전송하여 네이티브 코드가 UI 스레드에서 애니메이션을 수행할 수 있다. 애니메이션이 시작되면 JS 스레드가 차단되더라도 애니메이션에는 영향을 미치지 않는다.
애니메이션 구성에는 useNativeDriver: true를 지정하여 네이티브 드라이버를 사용할 수 있다. 자세한 내용은 애니메이션 가이드를 참조하자
애니메이션 가능한 컴포넌트만 애니메이션화할 수 있다. 이러한 컴포넌트들은 애니메이션 값을 속성에 바인딩하고 React의 렌더링 및 재조정 과정의 비용을 피하기 위해 타켓 네이티브 업데이트를 수행한다. 이 컴포넌트들은 언마운트 시 정리 작업도 처리하므로 기본적으로 안전하다.
createAnimatedComponent()를 사용하여 컴포넌트를 애니메이션 가능하게 만들 수 있다. Animated는 다음과 같은 애니메이션 가능한 컴포넌트를 제공한다.
Animated.ImageAnimated.ScrollViewAnimated.TextAnimated.ViewAnimated.FlatListAnimated.SectionList애니메이션은 다음과 같은 방식으로 결합할 수 있다.
Animated.delay(): 주어진 지연 후 애니메이션을 시작한다.Animated.parallel(): 여러 애니메이션을 동시에 시작한다.Animated.sequence(): 애니메이션을 순서대로 시작하고 각 애니메이션이 완료되면 다음 애니메이션을 시작한다.Animated.stagger(): 순차적이면서도 병렬적으로 애니메이션을 시작하고 연속적인 지연을 가진다.애니메이션은 하나의 애니메이션의 toValue를 다른 Animated.Value로 설정하여 체인(chain)할 수 있다.
두 개의 애니메이션 값을 덧셈, 뺄셈, 곱셈, 나눗셈 또는 모듈로(modulo)를 통해 결합하여 새로운 애니메이션 값을 만들 수 있다.
Animated.add()Animated.subtract()Animated.divide()Animated.modulo()Animated.multiply()Interpolation() 함수는 입력 범위를 다른 출력 범위에 매핑한다. 기본적으로 범위를 벗어난 경우에도 보간을 계속하지만, 출력 값을 제한(clamp)하도록 설정할 수도 있다. 기본적으로 선형 보간을 사용하여, 완화 함수를 지원한다.
자세한 내용은 애니메이션 가이드에서 확인하자
팬(pan) 또는 스크롤과 같은 제스처 및 기타 이벤트는 Animated.event()를 사용하여 애니메이션 값에 직접 매핑할 수 있다. 이는 구조화된 맵(map) 구문을 사용하여 이벤트 객체에서 값을 추출할 수 있도록 한다. 첫 번째 레벨은 여러 인수에 걸쳐 매핑할 수 있도록 배열 형태를 띠며, 배열은 중첩된 객체를 포함한다.
가로 스크롤 제스처를 처리할 때 event.nativeEvent.contentOffset.x를 scrollX(애니메이션 값)에 매핑하려면 다음과 같다.
onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
[{nativeEvent: {
contentOffset: {
x: scrollX
}
}
}]
)}