- 시력(UDVA)은 Line Chart를 사용하고, 구면도수(SPH)와 난시도수(CYL)는 Bar Chart를 사용했지만 대부분의 설정은 공통으로 사용하였다.
<ResponsiveContainer width="100%" height="100%">
<LineChart data={chartData}>
...
<Line />
</LineChart>
</ResponsiveContainer>
<ResponsiveContainer width="100%" height="100%">
<BarChart data={chartData}>
...
<Bar />
</BarChart>
</ResponsiveContainer>
- 실제로 차트 종류만 다를 뿐,
- ResponsiveContainer
- CartesianGrid
- XAxis
- YAxis
- 설정은 동일하게 적용하였다.
ResponsiveContainer
- 차트는 카드 크기에 따라 반응형으로 동작해야 했다.
- 그래서 ResponsiveContainer를 사용하여 부모 요소 크기에 맞게 자동으로 렌더링되도록 구성했다.
<ResponsiveContainer width="100%" height="100%">
CartesianGrid
- 차트의 가독성을 높이기 위해 배경 격자선을 추가하였다.
<CartesianGrid
vertical={false}
stroke="#E2E4E8"
/>
- 세로선은 제거하고 가로선만 표시하였다.
- 가로선만 남겨두면 값의 위치를 쉽게 파악할 수 있으면서도 화면이 복잡해 보이지 않는다.
XAxis
<XAxis
dataKey="label"
tick={renderXAxisTick}
tickLine={false}
axisLine={false}
padding={{ left: 60, right: 60 }}
/>
- dataKey="label"을 통해(chartData의 label을 사용한다는 뜻)
- 3일
- 3주
- 3개월
- 값을 표시하였다.
const chartData = [
{
label: "3일",
LASIK: ClampLineValue(data.LASIK?.["3days"]),
LASEK: ClampLineValue(data.LASEK?.["3days"]),
SMILE: ClampLineValue(data.SMILE?.["3days"]),
ICL: ClampLineValue(data.ICL?.["3days"]),
},
{
label: "3주",
LASIK: ClampLineValue(data.LASIK?.["3weeks"]),
LASEK: ClampLineValue(data.LASEK?.["3weeks"]),
SMILE: ClampLineValue(data.SMILE?.["3weeks"]),
ICL: ClampLineValue(data.ICL?.["3weeks"]),
},
{
label: "3개월",
LASIK: ClampLineValue(data.LASIK?.["3months"]),
LASEK: ClampLineValue(data.LASEK?.["3months"]),
SMILE: ClampLineValue(data.SMILE?.["3months"]),
ICL: ClampLineValue(data.ICL?.["3months"]),
},
];
- 기본 Tick 대신 커스텀 Tick을 사용하여 디자인 시스템에 맞는 폰트와 색상을 적용하였다.
const renderXAxisTick = ({ x, y, payload }: TickProps) => (
<text
x={Number(x)}
y={Number(y) + 24}
textAnchor="middle"
fill="#989DA8"
fontSize={16}
fontWeight={500}
letterSpacing="-0.6px"
>
{payload?.value}
</text>
);
YAxis
- Y축은 데이터 범위에 맞게 설정하였다.
- 시력 차트의 경우 0~1.2 범위를 사용하였다.
<YAxis
width={50}
domain={[0, 1.2]}
ticks={[0, 0.4, 0.8, 1.2]}
tick={renderYAxisTick}
tickLine={false}
axisLine={false}
/>
- 또한 모든 Tick Label(Y축 라벨)을 표시하는 대신 최소값과 최대값만 노출하였다.
- 0.4, 0.8은 라벨 안 보이게 함
const renderYAxisTick = ({ x, y, payload }: TickProps) => {
const value = Number(payload?.value);
if (value !== 0 && value !== 1.2) {
return null;
}
- 중간 값은 가이드 라인 역할만 수행하도록 구성하였다.
- 구면도수, 난시도수 차트의 경우
const yAxisConfig = {
sph: {
domain: [-1.5, 1.5],
ticks: [-1.5, 0, 1.5],
},
cyl: {
domain: [-1.5, 1.5],
ticks: [-1.5, 0, 1.5],
},
}[chartType];
const renderYAxisTick = ({ x, y, payload }: TickProps) => {
const value = Number(payload?.value);
return (
<text
x={Number(x) - 5}
y={Number(y)}
dy={value === -1.5 ? 2 : value === 0 ? 2 : -4}
dx={value === -1.5 ? -1 : 0}
textAnchor="end"
dominantBaseline="middle"
fill="#989DA8"
fontSize={16}
fontWeight={500}
letterSpacing="-0.6px"
>
{value.toFixed(2)}
</text>
);
};
차트 종류에 따른 렌더링
- 공통 설정 이후 실제 데이터 표현 방식만 달라진다.
Line Chart
- 시력(UDVA)은 시간에 따른 변화 추이를 확인하는 것이 중요했다.
- 그래서 Line Chart를 사용하였다.
<Line
dataKey={type}
stroke={chip.color}
strokeWidth={3}
dot={false}
activeDot={false}
isAnimationActive={false}
/>
- 수술 방식별 회복 추세 표현
- 점 제거
- Hover 제거
- PDF 출력을 위한 애니메이션 제거
- Bar Chart
Bar Chart
- 구면도수(SPH)와 난시도수(CYL)는 변화 추이보다 수치 비교가 중요했다.
- 그래서 동일한 데이터 구조를 사용하면서 렌더링 방식만 Bar Chart로 변경하였다.
<Bar
key={type}
dataKey={type}
fill={chip.color}
radius={[2, 2, 0, 0]}
isAnimationActive={false}
barSize={12}
/>