React Native로 커스터마이징 가능한 캐러셀 구축하기
2024-10-23 08:13:29React Native로 커스터마이징 가능한 캐러셀 구축하기
React Native에서 커스터마이징 가능한 캐러셀을 만드는 것은 애플리케이션에 시각적 매력과 상호작용을 추가하는 훌륭한 방법입니다. 이번 블로그에서는 React Native의 Animated 및 Reanimated 라이브러리를 활용하여 자동으로 스크롤되는 캐러셀을 구축하는 방법을 살펴보겠습니다. 또한 애니메이션 점과 우아한 이미지 전환 효과를 사용하여 페이지네이션 시스템을 구현할 것입니다.
개요
이번 튜토리얼에서 다룰 내용은 다음과 같습니다.
- 커스텀 캐러셀 컴포넌트 설정
- 부드러운 애니메이션과 보간을 위한 Reanimated 사용
- 자동 스크롤 기능으로 이미지를 자동으로 전환하기
- 현재 시각적인 항목에 따라 업데이트되는 페이지네이션 시스템 구축
우리가 만들어낼 것
- 애니메이션 전환을 이용한 수평 스크롤 캐러셀
- 사용자가 캐러셀과 상호작용할 때 멈추는 자동 스크롤
- 현재 표시된 항목에 따라 업데이트되는 페이지네이션 점
그럼 시작해볼까요?
1. 캐러셀 컴포넌트 설정하기
우선 CustomCarousel 컴포넌트를 생성하여 캐러셀의 핵심 로직을 담습니다. 주요 요소는 다음과 같습니다:
- Animated.FlatList를 이용한 항목 렌더링
- setInterval을 이용한 자동 스크롤 메커니즘
- Reanimated의 scrollTo 및 useSharedValue를 통한 전환 애니메이션
import React, { useEffect, useRef, useState } from 'react';
import { StyleSheet, View, useWindowDimensions } from 'react-native';
import Animated, {
scrollTo,
useAnimatedRef,
useAnimatedScrollHandler,
useDerivedValue,
useSharedValue,
} from 'react-native-reanimated';
import { hpx } from '../../helpers';
import Pagination from './Pagination';
import RenderItem from './RenderItem';
import { animals } from './constants';
const CustomCarousel = () => {
const x = useSharedValue(0);
const [data, setData] = useState(animals);
const { width } = useWindowDimensions();
const [currentIndex, setCurrentIndex] = useState(0);
const [paginationIndex, setPaginationIndex] = useState(0);
const ref = useAnimatedRef();
const [isAutoPlay, setIsAutoPlay] = useState(true);
const interval = useRef();
const offset = useSharedValue(0);
const onViewableItemsChanged = ({ viewableItems }) => {
if (viewableItems[0].index !== undefined) {
setCurrentIndex(viewableItems[0].index);
setPaginationIndex(viewableItems[0].index % animals.length);
}
};
const viewabilityConfig = {
itemVisiblePercentThreshold: 50,
};
const onScroll = useAnimatedScrollHandler({
onScroll: (e) => {
x.value = e.contentOffset.x;
},
onMomentumEnd: (e) => {
offset.value = e.contentOffset.x;
},
});
useDerivedValue(() => {
scrollTo(ref, offset.value, 0, true);
});
useEffect(() => {
if (isAutoPlay === true) {
interval.current = setInterval(() => {
offset.value += width;
}, 4000);
} else {
clearInterval(interval.current);
}
return () => {
clearInterval(interval.current);
};
}, [isAutoPlay, offset, width]);
return (
<View style={styles.container}>
<Animated.FlatList
ref={ref}
style={{ height: hpx(194), flexGrow: 0 }}
onScrollBeginDrag={() => {
setIsAutoPlay(false);
}}
onScrollEndDrag={() => {
setIsAutoPlay(true);
}}
onScroll={onScroll}
horizontal
bounces={false}
pagingEnabled
showsHorizontalScrollIndicator={false}
onEndReached={() => setData([...data, ...animals])}
data={data}
keyExtractor={(_, index) => `list_item${index}`}
renderItem={({ item, index }) => {
return <RenderItem item={item} index={index} x={x} />;
}}
/>
<Pagination paginationIndex={paginationIndex} />
</View>
);
};
export default CustomCarousel;
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
위의 코드는 캐러셀의 기본 구조를 설정합니다. Animated.FlatList를 통해 데이터를 수직으로 스크롤할 수 있게 합니다. useSharedValue와 useDerivedValue를 사용하여 애니메이션을 설정하고, 사용자의 상호작용에 따라 자동 스크롤을 제어합니다.
2. 페이지네이션 컴포넌트 구축하기
페이지네이션은 현재 활성화된 슬라이드를 표시하는 점을 표시합니다. 각 점은 현재 인덱스에 따라 불투명도가 변경되도록 설정됩니다.
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { hpx } from '../../helpers';
import Dot from './Dot';
import { animals } from './constants';
const Pagination = ({ paginationIndex }) => {
return (
<View style={styles.container}>
{animals.map((_, index) => {
return <Dot index={index} key={index} paginationIndex={paginationIndex} />;
})}
</View>
);
};
export default Pagination;
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
marginTop: hpx(16),
justifyContent: 'center',
alignItems: 'center',
},
});
Pagination 컴포넌트는 단순히 Dot 컴포넌트를 반복하여 렌더링합니다. 각 점은 인덱스에 따라 현재 활성 슬라이드를 자caption국하는 데 도움을 주고, 적절한 위치에 점이 배치됩니다.
3. 점 컴포넌트
Dot 컴포넌트는 페이지네이션 시스템의 각 점의 모양을 결정합니다. 현재 인덱스에 따라 스타일이 변경됩니다.
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Colors } from '../../assets';
import { hpx, wpx } from '../../helpers';
const Dot = ({ index, paginationIndex }) => {
return <View style={paginationIndex === index ? styles.dot : styles.dotOpacity} />;
};
export default Dot;
const styles = StyleSheet.create({
dot: {
backgroundColor: Colors.white,
height: hpx(3),
width: wpx(12),
marginHorizontal: 2,
borderRadius: 8,
},
dotOpacity: {
backgroundColor: Colors.white,
height: hpx(3),
width: wpx(12),
marginHorizontal: 2,
borderRadius: 8,
opacity: 0.5,
},
});
Dot 컴포넌트는 각 점을 스타일링하고, 현재 인덱스에 따라 보이도록 디자인하여 페이지네이션의 가독성을 높입니다.
4. RenderItem 컴포넌트
RenderItem 컴포넌트는 각 캐러셀 항목을 표시합니다. Reanimated의 보간 함수를 사용하여 각 항목이 스크롤할 때 불투명도를 애니메이션화합니다.
import React from 'react';
import { StyleSheet, useWindowDimensions, View } from 'react-native';
import Animated, { Extrapolation, interpolate, useAnimatedStyle } from 'react-native-reanimated';
import { hpx, nf, SCREEN_WIDTH, wpx } from '../../helpers/Scale';
const RenderItem = ({ item, index, x }) => {
const { width } = useWindowDimensions();
const animatedStyle = useAnimatedStyle(() => {
const opacityAnim = interpolate(
x.value,
[(index - 1) * width, index * width, (index + 1) * width],
[-0.3, 1, -0.3],
Extrapolation.CLAMP
);
return {
opacity: opacityAnim,
};
});
return (
<Animated.View style={[styles.itemContainer, animatedStyle]}>
{/* 각 항목에 대한 구성 요소나 이미지 표시 */}
</Animated.View>
);
};
export default RenderItem;
const styles = StyleSheet.create({
itemContainer: {
width: SCREEN_WIDTH,
height: hpx(194),
justifyContent: 'center',
alignItems: 'center',
},
});
이 컴포넌트는 스크롤 위치에 따라 불투명도를 조정하여 부드러운 이미지를 스크롤할 수 있도록 설정합니다.
결론
React Native에서 커스터마이징 가능한 캐러셀 만들기는 비주얼과 상호작용을 동시에 제공할 수 있는 좋은 기회입니다. 위의 방법을 활용하면 자동 스크롤과 페이지네이션을 포함한 매력적인 캐러셀을 쉽게 구축할 수 있습니다. 또한 Reanimated와 Animated 라이브러리를 통해 부드러운 애니메이션 효과를 제공하므로 사용자 경험이 한층 향상될 것입니다.
이 블로그의 내용을 통해 여러분도 멋진 캐러셀을 구현할 수 있기를 바랍니다. 더 많은 정보나 자료가 필요하다면 공식 React Native 문서나 Reanimated 문서를 참고하시기 바랍니다.