
nivo 라이브러리에서는 다양한 모양의 그래프를 제공한다.
나는 그중에서도 Line Chart를 선택했다.
코드가 되게 복잡한데.. 인터넷에 정보가 많이 없어서 직접 작성해봤다.
// 기본 구조
Array<{
id: string | number
data: Array<{
x: number | string | Date
y: number | string | Date
}>
}>
// 실제 코드
const Graph = () => {
const data = [{
id: 'line',
data: fcstData.map((item) => ({
x: formatTime(item.fcstDate, item.fcstTime),
y: parseFloat(item.fcstValue) || 0
}))
}]
...
}
그래프에 이용할 data를 선언해줘야 한다.
한 컴포넌트에 여러개의 line(그래프)을 표시할 수 있는데, 이때 id로 각 line을 구별할 수 있다.
...
return (
<div className='h-full w-full mb-[50px]'>
<ResponsiveLine
colors={'LightSkyBlue'}
data={data}
margin={{ top: 10, right: 40, bottom: 50, left: 60 }}
xFormat="time:%m월 %d일 %H:%M"
xScale={{
type: "time",
format: "%m/%d%H:%m",
useUTC: false,
min: 'auto',
max: 'auto',
}}
yFormat=" >-.2f"
yScale={{
type: "linear",
min: 'auto',
max: 'auto',
stacked: true,
reverse: false,
}}
axisBottom={{
format: '%m월%d일 %H:%M',
tickValues: 'every 1 hour',
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legendOffset: 36,
legendPosition: 'end',
truncateTickAt: 0
}}
axisLeft={{
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legendOffset: -40,
legendPosition: 'end',
truncateTickAt: 0
}}
curve='linear'
axisTop={null}
axisRight={null}
enableGridX={false}
pointSize={10}
pointColor={{ theme: 'background' }}
pointBorderWidth={2}
pointBorderColor={{ from: 'serieColor' }}
enablePointLabel={true}
pointLabel="data.yFormatted"
pointLabelYOffset={-12}
enableArea={true}
areaBaselineValue={minValue}
enableCrosshair={false}
enableTouchCrosshair={true}
useMesh={true}
legends={[]}
/>
</div>
)
부모 컴포넌트에 높이를 지정해주지 않으면 그래프가 렌더링되지 않는다. 무조건 height값을 지정해줘야 한다!
colors={'LightSkyBlue'}
data={data}
margin={{ top: 10, right: 40, bottom: 50, left: 60 }}
xFormat="time:%m월 %d일 %H:%M"
xScale={{
type: "time",
format: "%m/%d%H:%m",
useUTC: false,
min: 'auto',
max: 'auto',
}}

yFormat과 yScale도 이와 비슷하다.
axisBottom={{
format: '%m월%d일 %H:%M',
tickValues: 'every 1 hour',
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legendOffset: 36,
legend: 'time',
legendPosition: 'end',
truncateTickAt: 0
}}
axiosBottom은 x축에 대한 설정이다.

enableArea={true}
areaBaselineValue={minValue}
이 설정을 해줘야 그래프가 예쁘다..ㅎㅎ
curve='linear' // 선의 모양
enableGridX={false} // 배경으로 보일 그리드 선 표시 여부
pointSize={10} // 데이터 포인트의 크기
pointBorderWidth={2} // 데이터 포인트의 테두리 두께
enablePointLabel={true} // 포인트 label 표시 여부
pointLabel="data.yFormatted" // label을 뭐로 표시할 건지
pointLabelYOffset={-12} // 포인트와 label 사이 간격 지정
enableCrosshair={false} // 포인트에 마우스를 올렸을 때, 교차선의 표시 여부
useMesh={true} // 포인트에 마우스를 올렸을 때, 상호작용 활성화
import { ResponsiveLine } from '@nivo/line';
import { Fcst } from '../../util/interface';
interface Prop {
fcstData: Fcst[];
text: string;
style?: React.CSSProperties;
}
const formatTime = (d: string, t: string): string => {
const month = d.slice(4, 6);
const day = d.slice(6, 8);
const hours = t.slice(0, 2);
const minutes = t.slice(2, 4);
console.log(month);
return `${month}/${day}${hours}:${minutes}`;
}
const TempGraph: React.FC<Prop> = ({fcstData, text, style}) => {
const data = [{
id: 'line',
data: fcstData.map((item) => ({
x: formatTime(item.fcstDate, item.fcstTime),
y: parseFloat(item.fcstValue) || 0
}))
}]
const minValue = Math.min(...fcstData.map(item => parseFloat(item.fcstValue) || 0));
console.log(fcstData[0].fcstDate);
console.log(`graph ${text} data:`, data[0]);
return (
<div className='h-full w-full mb-[50px]' style={style}>
<p>{text}</p>
<ResponsiveLine
colors={'LightSkyBlue'}
data={data}
margin={{ top: 20, right: 40, bottom: 50, left: 60 }}
xFormat="time:%m월 %d일 %H:%M"
xScale={{
type: "time",
format: "%m/%d%H:%m",
useUTC: false,
min: 'auto',
max: 'auto',
}}
yScale={{
type: "linear",
min: 'auto',
max: 'auto',
stacked: true,
reverse: false,
}}
yFormat=" >-.2f"
curve='linear'
axisBottom={{
format: '%m월%d일 %H:%M',
tickValues: 'every 1 hour',
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legendOffset: 36,
truncateTickAt: 0
}}
axisLeft={{
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legendOffset: -40,
legendPosition: 'end',
truncateTickAt: 0
}}
enableGridX={true}
pointSize={10}
pointBorderWidth={1}
enablePointLabel={true}
pointLabel="data.yFormatted"
pointLabelYOffset={-12}
enableArea={true}
areaBaselineValue={minValue}
enableCrosshair={false}
useMesh={true}
/>
</div>
)
}
export default TempGraph
결과화면
