728x90
📊Chart.js 라이브러리로 달성률 시각화 구현하기(feat. Doughnut 차트)
‼️구현하고자 하는 것
- 전체 수행 날짜 대비 완료된 날짜의 비율을 계산하기
- Chart.js의 Doughnut 차트를 사용해 완료/미완료 비율을 시각적으로 표현하기
전체 수행 날짜 대비 완료된 날짜의 비율을 계산하기
HabitCard 컴포넌트 안에 자식인 HabitCardChart 컴포넌트를 넣어준다.
const startDate = new Date(habit.startDate)
const endDate = new Date(habit.endDate)
// frequency에 해당하는 요일을 계산
const frequencySet = new Set(habit.frequency.map((day) => day.toLowerCase())) // 요일을 소문자로 변환하여 Set 생성
// 총 수행 일수 계산 (frequency에 해당하는 요일만)
let totalDays = 0
for (
let date = new Date(startDate);
date <= endDate;
date.setDate(date.getDate() + 1)
) {
const dayOfWeek = date
.toLocaleString('default', { weekday: 'short' })
.toLowerCase()
if (frequencySet.has(dayOfWeek)) {
totalDays++
}
}
// 완료된 날짜 수 계산
const completedCount = habit.completedDates.length
// 달성률 계산
const achievementRate =
totalDays > 0 ? Math.floor((completedCount / totalDays) * 100) : 0
<HabitCardChart
completedCount={completedCount}
totalCount={totalDays}
/>
- 사용자가 지정한 시작일(startDate)과 종료일(endDate)을 기반으로 Date 객체를 생성한다.
- habit.frequency는 사용자가 습관을 실행하려는 요일 목록이다. habit.frequency에 포함된 요일(ex: ["Mon", "Wed", "Fri"])을 소문자로 변환 후 Set으로 저장해 중복 제거를 해준다.
- 시작일부터 종료일까지 하루씩 반복하며 각 날짜의 요일을 추출한다. (수행 요일(frequencySet)에 포함된 날짜만 카운트)
Chart.js의 Doughnut 차트를 사용해 완료/미완료 비율을 시각적으로 표현하기
Chart.js 설치 및 사용법
pnpm add chart.js react-chartjs-2
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
ChartJS.register(ArcElement, Tooltip, Legend);
- ArcElement: 도넛 차트의 조각을 그리는 역할
- Tooltip: 마우스오버 시 데이터 값을 표시하는 역할
- Legend: 차트의 범례를 그려주는 역할
❓register하는 이유
Chart.js는 경량화를 위해 모든 기능이 기본으로 포함되어 있지 않다.
사용자가 필요한 요소만 명시적으로 등록하면, 불필요한 코드를 제외해 번들 크기를 줄이고 성능을 최적화할 수 있다!
const data = {
labels: ['완료', '미완료'],
datasets: [
{
label: '달성률',
data: [completedCount, totalCount - completedCount],
backgroundColor: ['#1E4A19', '#edecdf'],
borderWidth: 1,
borderRadius: 8,
},
],
}
const options = {
responsive: true,
plugins: {
legend: {
position: 'bottom' as const,
labels: {
usePointStyle: true,
boxWidth: 5,
},
},
title: {
display: true,
text: '달성률',
},
},
}
Data (데이터)
- labels: 차트 조각의 이름 (예: ['완료', '미완료'])
- label: 데이터 세트의 이름
- data: 각 조각의 값
- backgroundColor: 조각 색상
- borderWidth: 조각의 테두리 두께
- borderRadius: 8 (약간 둥글느낌 원해서 넣었음)
+ 차트 옆에 옵션 추가해서 무슨 색이 어떤 라벨인지 표현할 수 있음!!
👇🏻풀코드👇🏻
'use client'
import { Doughnut } from 'react-chartjs-2'
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'
ChartJS.register(ArcElement, Tooltip, Legend)
type HabitCardChartProps = {
completedCount: number
totalCount: number
}
export default function HabitCardChart({
completedCount,
totalCount,
}: HabitCardChartProps) {
const data = {
labels: ['완료', '미완료'],
datasets: [
{
label: '달성률',
data: [completedCount, totalCount - completedCount],
backgroundColor: ['#1E4A19', '#edecdf'],
borderWidth: 1,
borderRadius: 8,
},
],
}
const options = {
responsive: true,
plugins: {
legend: {
position: 'bottom' as const,
labels: {
usePointStyle: true,
boxWidth: 5,
},
},
title: {
display: true,
text: '달성률',
},
},
}
return (
<div className="size-24 md:size-40">
<Doughnut data={data} options={options} />
</div>
)
}
위와 같은 방법으로 전체 루틴에 관한 총 달성률도 구현해봤다 🙂
참고
'🔥Next 뽀개기' 카테고리의 다른 글
Next.js App Router + PWA + Firebase로 알림 구현하기 (1) | 2025.01.26 |
---|---|
리액트 캘린더와 Firebase로 CRD 구현하기 (2) | 2024.12.16 |
Next.js Layout과 Firebase로 AuthGuard 구현하기(feat. cookie) (0) | 2024.12.01 |
Next.js에 firebase 연동해서 회원가입 구현하기 (0) | 2024.11.29 |
Zod + React Hook Form = 회원가입 뚝-딱! (0) | 2024.11.27 |