- Published on
- ·7 min read
진행률을 표시할 Progress Bar(Circle) 만들기 - React Native
개요
"소소한 단어장" 앱에는 해당 그룹 학습 진행률과 퀴즈 진행률을 표시하는 Progress Circle이 있습니다.
어떻게 적용했는지 정리해보겠습니다.
적용 화면
아래 이미지는 현재 서비스 되고 있는 앱에 적용된 화면입니다.

구현 과정
❗ 예제 코드의 스타일 및 함수 등은 포스팅을 위해 삭제 및 생략한 부분들이 있습니다.
1. react-native-svg 설치
svg를 이용하여 Progress Circle을 구현할 것이기 때문에 react-native-svg를 설치합니다.
npm i react-native-svg
2. Progress Circle 컴포넌트 생성
✨ Making a progress circle in React 코드를 기반으로 수정했습니다.
참고한 코드는 React용으로 작성되어 있어서 React Native에서 사용할 수 있도록 그리고 제 사용 용도에 맞도록 수정했습니다.
Pie.tsx
// https://dev.to/jackherizsmith/making-a-progress-circle-in-react-3o65
import Svg, {Circle, G, Text, TSpan} from 'react-native-svg';
const cleanPercentage = (percentage) => {
const tooLow = !Number.isFinite(+percentage) || percentage < 0;
const tooHigh = percentage > 100;
return tooLow ? 0 : tooHigh ? 100 : +percentage;
};
const PieCircle = ({ color, pct, radius = 50, borderWidth = 2 }:{
color: string;
pct?: number;
radius: number;
borderWidth: number;
}) => {
const circ = 2 * Math.PI * radius;
const strokePct = ((100 - pct) * circ) / 100;
return (
<Circle
r={radius}
cx={radius + borderWidth}
cy={radius + borderWidth}
fill="transparent"
fillRule={"nonzero"}
stroke={pct > 0 ? color : ""}
strokeWidth={borderWidth}
strokeDasharray={circ}
strokeDashoffset={pct ? strokePct : 0}
strokeLinecap="round"
></Circle>
);
};
const PieText = ({ percentage, title }) => {
return (
<Text
x="50%"
y="50%"
textAnchor="middle"
>
<TSpan x="50%" dy={0} fontSize={11} fontWeight={'bold'} fill={'#151A20'}>{title}</TSpan>
<TSpan x="50%" dy={14} fontSize={10} fill={'#151A20'}>{`${percentage}%`}</TSpan>
</Text>
);
};
const Pie = ({ percentage, color, title, radius = 50, borderWidth = 2}:{
percentage: number;
color: string;
title: string;
radius: number;
borderWidth: number;
}) => {
const pct = cleanPercentage(percentage);
const fullSize = (radius * 2)+(borderWidth*2);
return (
<Svg width={fullSize} height={fullSize}>
<G transform={`rotate(-90 ${radius + borderWidth} ${radius + borderWidth})`} fill={'white'}>
<Circle
r={radius}
cx={radius + borderWidth}
cy={radius + borderWidth}
fill={'#FFFFFF'}
></Circle>
<PieCircle borderWidth={borderWidth} radius={radius} color="#e3e3e3" pct={100} />
<PieCircle borderWidth={borderWidth} radius={radius} color={color} pct={pct} />
</G>
<PieText percentage={pct} title={title} />
</Svg>
);
};
export default Pie;
3. Progress Circle 적용
<Pie ... />
태그 사용radius
: 반지름 크기 지정borderWidth
: Progress Circle의 두께 지정percentage
: Progress Circle의 퍼센트 지정color
: Progress Circle 색상 지정title
: Progress Circle 텍스트 지정
<View>
<TouchableOpacity
accessibilityLabel={'학습'}
onPress={() => {}}>
<Pie radius={28} borderWidth={4} percentage={getLearnRate()} color={'#4285F4'} title={'학습'} />
</TouchableOpacity>
<View style={{width: 8}} />
<TouchableOpacity
accessibilityLabel={'퀴즈'}
onPress={() => {}}>
<Pie radius={28} borderWidth={4} percentage={getQuizRate()} color={'#4285F4'} title={'퀴즈'} />
</TouchableOpacity>
</View>
태그와 연관된 글
2023. 12. 17.
데이터 양이 많아지면서 발생한 React Native 앱 성능 문제 개선하기2023. 11. 21.
애드몹(AdMob) GDPR 적용 - React Native(안드로이드)2023. 11. 20.
애드몹(AdMob) GDPR 적용 - 안드로이드2023. 11. 02.
소소한 단어장 - 단어,문장 암기장 소개 (안드로이드)2023. 07. 25.
Color Picker(ambilwarna) 라이브러리 사용하여 색상 변경(안드로이드)