이전에 투표 기능 개발 했을 때는 애니메이션 없이 그냥 비율에 맞게 색상만 넣어주었다.
코드 리뷰 받으면서 시간 되면 애니메이션 적용도 해달라는 요청이 있어서 적용해보려고 한다.
우선 React-Native reanimated 라이브러리를 사용해서 진행하기에 해당 라이브러리가 설치 되어있어야 한다.
yarn add react-native-reanimated
애니메이션이 동작하기 위해서는 useSharedValue()
로 선언한 변수의 값이 변경이 되어야 원하는 애니메이션을 적용시킬 수 있다.
따라서 비율에 맞게 색상이 차오르는 애니메이션을 적용하기 위해서는 width 값을 useSharedValue
로 선언해주면 된다.
import Animated, {
useSharedValue,
withTiming,
Easing,
} from 'react-native-reanimated';
const VoteForm = ({ navigation, route }) => {
...
const width = useSharedValue(0);
...
}
변수 선언이 되었으면 해당 값을 변경시켜줘야 하는데, 투표하기 클릭했을 때 width의 값을 변경시켜주면 된다.
주의해야할 점은 인라인스타일로 width 값을 변경시키면 안된다.
따라서 투표 항목마다의 width를 변경시키기 위해 ActiveItemBar라는 커스텀 컴포넌트를 만들어준 뒤 해당 컴포넌트안에 useSharedValue
를 다시 선언해줬다.
그러면 각 투표 항목마다 useSharedValue
가 생성되어 독립적으로 값을 변경시킬 수 있다.
// 애니메이션 적용한 투표 항목 컴포넌트
const ActiveItemBar = (props) => {
const { ratio } = props;
const width = useSharedValue('0%');
(() => {
width.value = withTiming(`${ratio}%`, {
duration: 500,
easing: Easing.linear,
});
})();
return (
<Animated.View
style={{
backgroundColor: voteTheme.voteSubmitBtn,
position: 'absolute',
width: width,
height: '100%',
borderRadius: 11,
}}
></Animated.View>
);
};
const VoteForm = ({ navigation, route }) => {
...
return (
<View style={{ flex: 1, gap: 8, marginTop: 16 }}>
{data.vote?.map((item, index) => (
...
{isVote && (
<ActiveItemBar
ratio={
(VOTER.filter((v) => v.vote === index).length / VOTER.length) * 100
}
/>
)}
...
</View>
}
투표한 항목의 비율을 ratio라는 props로 넘겨주었다.
width는 useSharedValue(’0%’)로 선언해주고, 넘겨 받은 ratio로 값을 변경시켜주면된다.