원리와 예제를 통한 react-native-reanimated2 입문
4 min readSep 29, 2023
이 글은 올룰로 Confluence에 작성했던 글을 보관용으로 재포스팅 하는 것이다.
react-native-reanimated1
- Functional Component 형의 코딩만 지원
- View Property type number/string만 지원
Worklet
UI Thread에서 JS Thread에 접근 가능한 함수 지정하는 키워드
function workletFunc() {
'worklet';
//...
}
- View Property를 변경하거나 이벤트에 반응하는 callback
SharedValue
JS / UI Thread 모두에서 접근가능한 변수
UI Thread에서 읽는데 동기로 변경
JS Thread에서는 비동기로 변경됨
- 다음 Rendering에 적용됨
예제
import {useSharedValue} from 'react-native-reanimated';
// in component
...
const sharedValue = useSharedValue(0);
console.log(sharedValue.value);
Example
Pan Gesture로 View가 손가락을 따라 움직이는 애니메이션 구현
// in component
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const onGestureEventHandler = useAnimatedGestureHandler<
PanGestureHandlerGestureEvent,
{translateX: number; translateY: number}
>({
onStart: (_, ctx) => {
ctx.translateX = translateX.value;
ctx.translateY = translateY.value;
},
onActive: (e, ctx) => {
translateX.value = clamp(
ctx.translateX + e.translationX,
0,
widthLimit - BOX_WIDTH,
);
translateY.value = clamp(
ctx.translateY + e.translationY,
0,
heightLimit - BOX_HEIGHT,
);
},
onEnd: (e, _) => {
translateX.value = withBouncing(
withDecay({velocity: e.velocityX}),
0,
widthLimit - BOX_WIDTH,
);
translateY.value = withBouncing(
withDecay({velocity: e.velocityY}),
0,
heightLimit - BOX_HEIGHT,
);
},
});
const animStyle = useAnimatedStyle(() => {
return {
transform: [
{translateX: translateX.value},
{translateY: translateY.value},
],
};
});
return (
<View>
<PanGestureHandler onGestureEvent={onGestureEventHandler}>
<Animated.View style={animStyle}>
<DragableView width={VIEW_WIDTH} height={VIEW_HEIGHT} />
</Animated.View>
</PanGestureHandler>
</View>
);