Skip to main content
Version: Next

애니메이션

Animated 라이브러리는 애니메이션을 유연하고 강력하게 만들며, 쉽게 구축하고 유지할 수 있도록 설계되었다. Animated는 입력과 출력 간의 선언적 관계, 그 사이에서 설정 가능한 변환, 그리고 시간 기반 애니메이션 실행을 제어하는 start/stop 메서드에 초점을 맞춘다.

애니메이션을 생성하는 핵심 워크플로는 Animated.Value를 만들고, 이를 애니메이션 컴포넌트의 하나 이상의 스타일 속성에 연결한 다음, Animated.timing()을 사용해 애니메이션을 통해 업데이트를 구동하는 것이다.

애니메이션 값을 직접 수정하지 않는다. useRef을 사용해 변경 가능한 ref 객체를 반환할 수 있다. 이 ref 객체의 current 속성은 주어진 인자로 초기화되며, 컴포넌트 생명주기 동안 유지된다.

예제

다음 예제는 애니메이션 값 fadeAnim에 따라 점점 나타나거나 사라지는 View를 보여준다.

Animated를 사용한 더 많은 예제는 애니메이션 가이드를 참고한다.

개요

Animated와 함께 사용할 수 있는 값 타입은 두 가지가 있다:

Animated.Value는 스타일 속성이나 다른 프로퍼티에 바인딩할 수 있으며, 보간(interpolate)도 가능하다. 하나의 Animated.Value로 여러 프로퍼티를 제어할 수 있다.

애니메이션 설정하기

Animated는 세 가지 유형의 애니메이션을 제공한다. 각 애니메이션 유형은 초기 값에서 최종 값으로 변화하는 방식을 제어하는 특정 애니메이션 곡선을 제공한다:

대부분의 경우 timing()을 사용하게 된다. 기본적으로 이 함수는 대칭적인 easeInOut 곡선을 사용해 객체가 점점 가속하다가 최고 속도에 이르고, 다시 점점 감속해 멈추는 효과를 준다.

애니메이션은 start()를 호출해 시작한다. start()는 애니메이션이 완료될 때 호출되는 콜백 함수를 인자로 받는다. 애니메이션이 정상적으로 완료되면 콜백 함수는 {finished: true}와 함께 호출된다. 애니메이션이 완료되기 전에 stop()이 호출되어 중단된 경우(예: 제스처나 다른 애니메이션에 의해 중단된 경우), 콜백 함수는 {finished: false}를 받는다.

tsx
Animated.timing({}).start(({finished}) => {
/* 완료 콜백 */
});

네이티브 드라이버 사용하기

네이티브 드라이버를 사용하면 애니메이션을 시작하기 전에 애니메이션 관련 모든 정보를 네이티브로 전송한다. 이렇게 하면 네이티브 코드가 UI 스레드에서 애니메이션을 수행할 수 있으며, 매 프레임마다 브릿지를 거칠 필요가 없다. 애니메이션이 시작된 후에는 JS 스레드가 블로킹되더라도 애니메이션에 영향을 미치지 않는다.

애니메이션 설정에서 useNativeDriver: true를 지정해 네이티브 드라이버를 사용할 수 있다. 더 자세한 내용은 애니메이션 가이드를 참고한다.

애니메이션 가능한 컴포넌트

애니메이션 가능한 컴포넌트만 애니메이션을 적용할 수 있다. 이 특별한 컴포넌트들은 애니메이션 값을 속성에 바인딩하고, 매 프레임마다 React의 리렌더링과 조정 과정을 거치지 않도록 네이티브 업데이트를 수행한다. 또한 언마운트 시 자동으로 정리 작업을 처리해 기본적으로 안전하다.

Animated는 위의 래퍼를 사용해 다음과 같은 애니메이션 가능한 컴포넌트를 제공한다:

  • Animated.Image
  • Animated.ScrollView
  • Animated.Text
  • Animated.View
  • Animated.FlatList
  • Animated.SectionList

애니메이션 합성하기

애니메이션은 합성 함수를 사용해 복잡한 방식으로 조합할 수 있다:

  • Animated.delay()는 주어진 지연 시간 후에 애니메이션을 시작한다.
  • Animated.parallel()은 여러 애니메이션을 동시에 시작한다.
  • Animated.sequence()는 애니메이션을 순서대로 시작하며, 각 애니메이션이 완료된 후 다음 애니메이션을 시작한다.
  • Animated.stagger()는 애니메이션을 순서대로 시작하지만, 연속적인 지연 시간을 두고 병렬로 실행한다.

또한 한 애니메이션의 toValue를 다른 Animated.Value로 설정해 애니메이션을 연쇄적으로 연결할 수도 있다. 자세한 내용은 동적 값 추적하기를 참고한다.

기본적으로 한 애니메이션이 중단되거나 방해받으면, 그룹 내 다른 모든 애니메이션도 중단된다.

애니메이션 값 결합하기

두 애니메이션 값을 더하거나, 빼거나, 곱하거나, 나누거나, 나머지를 구하는 방식으로 결합하여 새로운 애니메이션 값을 만들 수 있다:

보간법(Interpolation)

interpolate() 함수는 입력 범위를 다양한 출력 범위로 매핑할 수 있게 해준다. 기본적으로 이 함수는 주어진 범위를 넘어서도 곡선을 외삽(extrapolate)하지만, 출력 값을 고정(clamp)하도록 설정할 수도 있다. 기본적으로 선형 보간법(linear interpolation)을 사용하지만, 이징 함수(easing functions)도 지원한다.

보간법에 대한 더 자세한 내용은 애니메이션 가이드에서 확인할 수 있다.

제스처 및 이벤트 처리

패닝이나 스크롤링 같은 제스처와 기타 이벤트는 Animated.event()를 사용해 애니메이션 값에 직접 매핑할 수 있다. 이를 위해 구조화된 맵 문법을 사용해 복잡한 이벤트 객체에서 값을 추출한다. 첫 번째 레벨은 여러 인자를 매핑할 수 있도록 배열로 구성되며, 이 배열은 중첩된 객체를 포함한다.

예를 들어, 수평 스크롤링 제스처를 다룰 때 event.nativeEvent.contentOffset.xscrollX(Animated.Value)에 매핑하려면 다음과 같이 작성한다:

tsx
 onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
[{nativeEvent: {
contentOffset: {
x: scrollX
}
}
}]
)}

참조

메서드

주어진 값이 Value 대신 ValueXY 타입일 때, 각 설정 옵션은 스칼라 값 대신 {x: ..., y: ...} 형태의 벡터로 지정할 수 있다.

decay()

tsx
static decay(value, config): CompositeAnimation;

초기 속도를 기반으로 감쇠 계수를 사용해 값을 0까지 애니메이션 처리한다.

config는 다음과 같은 옵션을 가진 객체다:

  • velocity: 초기 속도. 필수 값이다.
  • deceleration: 감쇠율. 기본값은 0.997이다.
  • isInteraction: 이 애니메이션이 InteractionManager에 "인터랙션 핸들"을 생성할지 여부. 기본값은 true이다.
  • useNativeDriver: true일 경우 네이티브 드라이버를 사용한다. 필수 값이다.

timing()

tsx
static timing(value, config): CompositeAnimation;

주어진 값을 시간에 따라 이징 곡선을 따라 애니메이션화한다. Easing 모듈에는 다양한 미리 정의된 곡선이 있으며, 커스텀 함수를 사용할 수도 있다.

config는 다음과 같은 옵션을 가진 객체다:

  • duration: 애니메이션의 길이(밀리초). 기본값은 500이다.
  • easing: 곡선을 정의하는 이징 함수. 기본값은 Easing.inOut(Easing.ease)이다.
  • delay: 애니메이션 시작 전 지연 시간(밀리초). 기본값은 0이다.
  • isInteraction: 이 애니메이션이 InteractionManager에 "인터랙션 핸들"을 생성하는지 여부. 기본값은 true이다.
  • useNativeDriver: true일 경우 네이티브 드라이버를 사용한다. 필수 항목이다.

spring()

tsx
static spring(value, config): CompositeAnimation;

spring()감쇠 조화 진동을 기반으로 한 해석적 스프링 모델에 따라 값을 애니메이션화한다. toValue가 업데이트될 때 유연한 동작을 만들기 위해 속도 상태를 추적하며, 체이닝도 가능하다.

config는 다음과 같은 옵션을 가진 객체다. 단, bounciness/speed, tension/friction, 또는 stiffness/damping/mass 중 하나만 정의할 수 있으며, 둘 이상을 동시에 정의할 수 없다는 점에 유의하자.

friction/tension 또는 bounciness/speed 옵션은 Facebook Pop, Rebound, Origami의 스프링 모델과 일치한다.

  • friction: "튕김" 정도/오버슈트를 제어한다. 기본값은 7이다.
  • tension: 애니메이션 속도를 제어한다. 기본값은 40이다.
  • speed: 애니메이션 속도를 제어한다. 기본값은 12이다.
  • bounciness: 튕김 정도를 제어한다. 기본값은 8이다.

stiffness/damping/mass를 매개변수로 지정하면 Animated.spring감쇠 조화 진동의 운동 방정식을 기반으로 한 해석적 스프링 모델을 사용한다. 이 동작은 스프링 역학의 물리적 원리를 더 정확하고 충실하게 따르며, iOS의 CASpringAnimation 구현과 유사하다.

  • stiffness: 스프링 강성 계수. 기본값은 100이다.
  • damping: 마찰력에 의해 스프링의 움직임이 어떻게 감쇠되어야 하는지 정의한다. 기본값은 10이다.
  • mass: 스프링 끝에 부착된 물체의 질량. 기본값은 1이다.

기타 구성 옵션은 다음과 같다:

  • velocity: 스프링에 부착된 물체의 초기 속도. 기본값은 0(정지 상태)이다.
  • overshootClamping: 스프링이 튀지 않고 고정되어야 하는지 여부를 나타내는 불리언 값. 기본값은 false이다.
  • restDisplacementThreshold: 스프링이 정지 상태로 간주되기 위한 변위 임계값. 기본값은 0.001이다.
  • restSpeedThreshold: 스프링이 정지 상태로 간주되기 위한 속도 임계값(픽셀/초). 기본값은 0.001이다.
  • delay: 애니메이션 시작 전 지연 시간(밀리초). 기본값은 0이다.
  • isInteraction: 이 애니메이션이 InteractionManager에 "interaction handle"을 생성하는지 여부. 기본값은 true이다.
  • useNativeDriver: true일 경우 네이티브 드라이버를 사용한다. 필수 값이다.

add()

tsx
static add(a: Animated, b: Animated): AnimatedAddition;

두 Animated 값을 더해 새로운 Animated 값을 생성한다.

subtract()

tsx
static subtract(a: Animated, b: Animated): AnimatedSubtraction;

첫 번째 Animated 값에서 두 번째 Animated 값을 뺀 새로운 Animated 값을 생성한다.

divide()

tsx
static divide(a: Animated, b: Animated): AnimatedDivision;

첫 번째 Animated 값을 두 번째 Animated 값으로 나누어 새로운 Animated 값을 생성한다.

multiply()

tsx
static multiply(a: Animated, b: Animated): AnimatedMultiplication;

두 Animated 값을 곱한 결과로 새로운 Animated 값을 생성한다.

modulo()

tsx
static modulo(a: Animated, modulus: number): AnimatedModulo;

제공된 Animated 값의 (음수가 아닌) 모듈로를 계산하여 새로운 Animated 값을 생성한다.

diffClamp()

tsx
static diffClamp(a: Animated, min: number, max: number): AnimatedDiffClamp;

두 값 사이로 제한된 새로운 Animated 값을 생성한다. 이 함수는 마지막 값과의 차이를 사용하기 때문에, 값이 범위에서 멀리 떨어져 있어도 다시 범위에 가까워지기 시작하면 값이 변하기 시작한다. (value = clamp(value + diff, min, max)).

이 기능은 스크롤 이벤트와 함께 사용하기에 유용하다. 예를 들어, 스크롤을 올릴 때 네비게이션 바를 보여주고, 스크롤을 내릴 때 숨기는 경우에 활용할 수 있다.

delay()

tsx
static delay(time: number): CompositeAnimation;

주어진 시간만큼 지연 후 애니메이션을 시작한다.

sequence()

tsx
static sequence(animations: CompositeAnimation[]): CompositeAnimation;

여러 애니메이션을 순차적으로 실행한다. 각 애니메이션이 완료된 후에 다음 애니메이션을 시작한다. 현재 실행 중인 애니메이션이 중단되면, 이후 애니메이션은 시작되지 않는다.

parallel()

tsx
static parallel(
animations: CompositeAnimation[],
config?: ParallelConfig
): CompositeAnimation;

여러 애니메이션을 동시에 시작한다. 기본적으로 하나의 애니메이션이 중단되면 모든 애니메이션이 중단된다. 이 동작은 stopTogether 플래그를 통해 변경할 수 있다.

stagger()

tsx
static stagger(
time: number,
animations: CompositeAnimation[]
): CompositeAnimation;

애니메이션 배열은 병렬로 실행될 수 있지만, 연속적인 지연과 함께 순차적으로 시작된다. 이는 트레일링 효과를 구현하는 데 유용하다.

loop()

tsx
static loop(
animation: CompositeAnimation[],
config?: LoopAnimationConfig
): CompositeAnimation;

주어진 애니메이션을 지속적으로 반복한다. 애니메이션이 끝에 도달하면 초기 상태로 돌아가 다시 시작한다. 자식 애니메이션이 useNativeDriver: true로 설정된 경우, JS 스레드를 블로킹하지 않고 반복한다. 또한, 애니메이션이 실행 중일 때 VirtualizedList 기반 컴포넌트가 추가 행을 렌더링하지 못하게 할 수 있다. 이를 해결하려면 자식 애니메이션 설정에서 isInteraction: false를 전달하면 된다.

config는 다음과 같은 옵션을 가질 수 있는 객체다:

  • iterations: 애니메이션을 반복할 횟수. 기본값은 -1(무한 반복)이다.

event()

tsx
static event(
argMapping: Mapping[],
config?: EventConfig
): (...args: any[]) => void;

매핑 배열을 인자로 받아 각 인자에서 값을 추출한 후, 매핑된 출력에 대해 setValue를 호출한다. 예를 들어:

tsx
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {x: this._scrollX}}}],
{listener: (event: ScrollEvent) => console.log(event)}, // 선택적 비동기 리스너
)}
...
onPanResponderMove: Animated.event(
[
null, // 원시 이벤트 인자는 무시
{dx: this._panX},
], // 제스처 상태 인자
{
listener: (
event: GestureResponderEvent,
gestureState: PanResponderGestureState
) => console.log(event, gestureState),
} // 선택적 비동기 리스너
);

config는 다음과 같은 옵션을 가질 수 있는 객체다:

  • listener: 선택적 비동기 리스너.
  • useNativeDriver: true일 경우 네이티브 드라이버를 사용한다. 필수 항목.

forkEvent()

jsx
static forkEvent(event: AnimatedEvent, listener: Function): AnimatedEvent;

이 API는 props를 통해 전달된 애니메이션 이벤트를 감시하기 위한 고급 명령형 API이다. 기존 AnimatedEvent에 새로운 자바스크립트 리스너를 추가할 수 있다. animatedEvent가 자바스크립트 리스너인 경우, 두 리스너를 하나로 병합한다. animatedEvent가 null 또는 undefined인 경우, 자바스크립트 리스너를 직접 할당한다. 가능한 경우 값을 직접 사용한다.

unforkEvent()

jsx
static unforkEvent(event: AnimatedEvent, listener: Function);

start()

tsx
static start(callback?: (result: {finished: boolean}) => void);

애니메이션을 시작하려면 애니메이션 객체에서 start()를 호출한다. start()는 애니메이션이 완료되거나, 완료되기 전에 stop()이 호출되어 종료될 때 실행될 완료 콜백을 인자로 받는다.

매개변수:

이름타입필수 여부설명
callback(result: {finished: boolean}) => void아니오애니메이션이 정상적으로 완료되거나, 완료되기 전에 stop()이 호출되어 종료될 때 호출될 함수

콜백을 사용한 start() 예제:

tsx
Animated.timing({}).start(({finished}) => {
/* 완료 콜백 */
});

stop()

tsx
static stop();

실행 중인 애니메이션을 중지한다.

reset()

tsx
static reset();

실행 중인 애니메이션을 중지하고 값을 원래 상태로 초기화한다.

속성

Value

애니메이션을 제어하는 표준 값 클래스. 일반적으로 useAnimatedValue(0); 또는 클래스 컴포넌트에서 new Animated.Value(0);으로 초기화한다.

Animated.Value API에 대한 자세한 내용은 별도의 페이지에서 확인할 수 있다.

ValueXY

2D 애니메이션을 제어하기 위한 2D 값 클래스. 예를 들어, 패닝 제스처를 구현하는 데 사용한다.

Animated.ValueXY API에 대한 자세한 내용은 별도의 페이지에서 확인할 수 있다.

Interpolation

Interpolation 타입을 Flow에서 사용하기 위해 내보냈다.

Node

타입 검사를 쉽게 하기 위해 내보낸 클래스입니다. 모든 애니메이션 값은 이 클래스에서 파생됩니다.

createAnimatedComponent

어떤 React 컴포넌트든 애니메이션 적용이 가능하도록 만든다. Animated.View 등을 생성할 때 사용한다.

attachNativeEvent

뷰의 이벤트에 애니메이션 값을 연결하기 위한 명령형 API. 가능하다면 useNativeDriver: true를 사용한 Animated.event를 우선적으로 사용한다.