[React] Recharts 라이브러리로 그래프 그리기 (커스텀 하는 법)

@eunjios·2023년 11월 3일
1
post-thumbnail

Preview

Recharts 라이브러리를 사용해서 이렇게 생긴 라인 차트를 만들어보자.


Recharts API

Recharts 로 라인 차트 뿐만 아니라 Bar, Area, Composed, Pie 등 다양한 차트를 만들 수 있으니 해당 부분은 공식 문서를 참고하자.

이 포스트에서는 Line Chart 와 위 차트를 구현하는데 필요한 컴포넌트 및 props의 API만 정리할 예정이다.


LineChart

라인 차트를 커스텀 해보자. 전체 props는 Docs에서 확인할 수 있다.

data

<LineChart data={someData}></LineChart>

차트를 그릴 데이터를 지정한다.

width/height

<LineChart width={800} height={400}></LineChart>

차트의 너비와 높이를 지정한다. 단, 부모 컴포넌트 <ResponsiveContainer> 로 width와 height를 지정한다면, 라인 차트의 너비와 높이는 지정하지 않는다.

margin

<LineChart margin={{ top: 5, right: 5, bottom: 5, left: 5 }}></LineChart>

차트의 margin을 커스텀한다.

onClick/onMouseEnter/onMouseMove/onMouseLeave

const mouseEnterHandler = () => {
  setIsEntered(true);
};
<LineChart onMouseEnter={mouseEnterHandler}></LineChart>

각 이벤트가 발생할 때 실행할 핸들러 함수를 지정한다.


Child Components

LineChart의 자식 컴포넌트는 다음과 같다.

component역할
<XAxis />X축
<YAxis />Y축
<ReferenceArea />특정 영역 강조 표시
<ReferenceDot />특정 값 강조 표시 (점)
<ReferenceLine />특정 값 강조 표시 (선)
<Brush />X값 중 일부 영역의 데이터만 보여주기 (이동 가능)
<CartesianGrid />그래프 그리드 보조선
<Legend />그래프 범례
<Tooltip />커서 가져가면 보여지는 네모 박스
<Line />그래프 직선
<Customized />

이 중 필요한 컴포넌트만 다음과 같이 구성했다.

<ResponsiveContainer>
  <LineChart>
    <XAxis />
    <YAxis />
    <Tooltip />
    <ReferenceLine />
    <Line />
  </LineChart>
</ResponsiveContainer>

XAxis/YAxis

x축을 커스텀 해보자. 전체 내용은 Docs에서 확인할 수 있다. y축도 비슷한 props 를 가지므로 한꺼번에 정리하자.

dataKey

<XAxis dataKey='createdAt' />

LineChart 에서 지정했던 데이터 중 축이 될 데이터의 키를 지정한다.

type

<XAxis type='category' />

'category' 혹은 'number' 로 축의 타입을 지정한다. 'category' 의 경우 범주형, 'number' 의 경우 연속형 데이터를 의미한다.

domain

<XAxis type="number" domain={['dataMin', 'dataMax']} />
<XAxis type="number" domain={[0, 'dataMax']} />
<XAxis type="number" domain={['auto', 'auto']} />
<XAxis type="number" domain={[0, 'dataMax + 1000']} />
<XAxis type="number" domain={['dataMin - 100', 'dataMax + 100']} />
<XAxis type="number" domain={[dataMin => (0 - Math.abs(dataMin)), dataMax => (dataMax * 2)]} />
<XAxis type="number" domain={([dataMin, dataMax]) => { const absMax = Math.max(Math.abs(dataMin), Math.abs(dataMax)); return [-absMax, absMax]; }} />

축의 범위를 지정한다. 최소부터 최대, 자동 지정, 최대 + 1000 등 다양한 도메인을 지정할 수 있다.

tickLine

<XAxis tickLine={false} />

default 값은 true로 축에 tick line (눈금선)이 있다. 이를 없애고 싶으면 false로 설정한다.

stroke

<XAxis stroke='#eee' />

x축/y축의 색상을 지정한다.

padding

<XAxis padding={{ left: '8px', right: '8px' }} />
<YAxis padding={{ top: '4px', bottom: '8px' }} />

x축/y축의 padding을 지정한다. 단 x축은 left와 right만 지정할 수 있고, y축은 top과 bottom만 지정할 수 있다.

tickFormatter

축에 표시되는 숫자 (혹은 글자) 형태를 지정할 수 있다.

예를 들어, 다음과 같은 데이터가 있다고 하자. 여기서 x축을 date로 하고, y축을 price로 한다고 가정하자.

const data = [
  {
    id: 1,
    price: 10000,
    createdAt: '20231103',
  },
  {
    id: 2,
    price: 12000,
    createdAt: '20231104'
  },
];

이 때 x축에 표시되는 문자는 20231103 과 20231104 이고, y축에 표시되는 문자는 10000, 12000 이다. 이를 커스텀하기 위해 tickFormatter 를 사용한다. 예를 들어 '00월 00일', '00,000원' 과 같은 형태로 커스텀 할 수 있다.

formatter 함수 정의

const formatXAxis = (xTick: string) => {
  return `${xTick.substring(4, 6)}${xTick.substring(6, 8)}`;
};

const formatYAxis = (yTick: number) => {
  return `${yTick.toLocaleString()}`;
};

formatter 적용

<XAxis tickFormatter={formatXAxis} />
<YAxis tickFormatter={formatYAxis} />

hide

<YAxis hide />
<YAxis hide={windowWidth.innerWidth.current < 767} />

hide를 사용할 경우 해당 축이 사라진다. 화면의 너비 등을 기준으로 하여 축을 보여줄 경우와 숨길 경우를 정할 수 있다.


Line

라인 차트의 선을 커스텀 해보자. 전체 내용은 Docs에서 확인할 수 있다.

dataKey

<Line dataKey='price' />

그래프의 y값이 될 데이터의 key를 지정한다.

type

<Line type='linear' />

라인 차트의 타입을 지정한다. 다음과 같이 다양한 타입이 있다.

'basis' | 'basisClosed' | 'basisOpen' | 'bumpX' | 'bumpY' | 'bump' | 'linear' | 'linearClosed' | 'natural' | 'monotoneX' | 'monotoneY' | 'monotone' | 'step' | 'stepBefore' | 'stepAfter' 

dot

<Line dataKey="value" dot={false} />
<Line dataKey="value" dot={{ stroke: 'red', strokeWidth: 2 }} />
<Line dataKey="value" dot={<CustomizedDot />} />
<Line dataKey="value" dot={renderDot} />

라인 차트의 점을 커스텀할 수 있다. dot의 타입은 boolean, 객체, 함수, ReactElement 이다.

activeDot

activeDot은 마우스 커서와 가까운 점 (= active 상태인 점)을 커스텀 할 수 있다. dot과 동일하게 boolean, 객체, 함수, ReactElement 타입을 가진다.

예를 들어, 기본 점은 검은색이고, active 상태의 점은 빨간색으로 지정하고 싶다면 다음과 같이 구현할 수 있다.

<Line 
  dataKey="value" 
  dot={{ fill: 'black', stroke: 'black' }}
  activeDot={{ fill: 'red', stroke: 'red' }} 
/>

stroke

<Line stroke='black' />

라인 차트의 선 색상을 지정한다.

strokeWidth

<Line strokeWidth={2} />

라인 차트의 선 굵기를 지정한다.


ReferenceLine

라인 차트에 보조선을 추가해보자. 전체 내용은 Recharts API - ReferenceLine에서 확인할 수 있다.

x/y

보조선의 값을 지정할 수 있다. 예를 들어, y=30, x='monday' 인 보조선을 추가하고 싶다면 다음과 같이 할 수 있다.

<ReferenceLine y={30} />
<ReferenceLine x='monday' />

단, 여기서 y축은 type='number' x축은 type='category' 이다. 타입이 카테고리인 경우 반드시 카테고리 중 하나의 값을 지정해줘야 한다.

stroke

<ReferenceLine stroke='#eee' />

보조선의 색상을 지정할 수 있다.

label

<ReferenceLine label='Max' />

보조선에 이름을 표시할 수 있다.

strokeDasharray

<ReferenceLine strokeDasharray="3 3" />

보조선을 dash 형태로 나타낼 수 있다.


Tooltip

마우스 커서를 가까이 했을 때 생기는 네모 박스 Tooltip 을 커스텀 해보자.

separator

name과 value 사이를 구분짓는 구분자 커스텀. 기본 값은 : 이다.

ex) 가격 - 10000
<Tooltip separator='-' />

formatter

Tooltip content 형태를 지정한다.

ex) 가격 - 10,000원
// fromatter 정의
const formatTooltip = (value: number) => {
  return `${value.toLocaleString()}`;
};
// formatter 적용
<Tooltip formatter={formatTooltip} />

labelFormatter

Tooltip의 label (제목) 형태를 지정한다.

ex)
11월 03일 가격 정보
가격 - 10,000원
// formatter 정의
const formatTooltipLabel = (value: string) => {
  return `${value.substring(4, 6)}${value.substring(6, 8)}일 가격 정보`;
  };
};
// formatter 적용
<Tooltip labelFormatter={formatTooltipLabel} />

wrapperStyle

<Tooltip wrapperStyle={{ padding: '8px', textAlign: 'left' }} />

Tooltip 컨테이너의 스타일을 지정한다.

contentStyle

<Tooltip contentStyle={{ fontWeight: 700, color: '#333' }} />

Tooltip content (내용) 의 폰트 사이즈, 폰트 굵기, 색상, 마진 등 스타일을 지정한다.

labelStyle

<Tooltip 
  labelStyle={{
    fontSize: '12px',
    marginBottom: '8px',
    fontWeight: 700,
    color: '#555',
  }}
/>

Tooltip label (제목) 의 폰트 사이즈, 폰트 굵기, 색상, 마진 등 스타일을 지정한다.

cursor

<Tooltip cursor={{ stroke: '#eee', strkeWidth: 1 }} />

마우스를 가져갔을 때 생기는 세로줄 (커서) 의 스타일을 지정한다.


content={CustomTooltip}

위 내용을 하나의 커스텀 컴포넌트로 만드는 방법이다. dataKey로 설정한 key가 아니어도 payload를 통해 접근할 수 있다.

예를 들어, <LineChart data={data} /> 로 데이터를 지정했을 때, data의 형태가 다음과 같고, Line과 XAxis의 dataKey가 각각 price와 createdAt라 하자.

interface data {
  price: number;
  createdAt: string;
  diff: number;
}[]

이 때 우리는 payload[0].payload 를 사용하여 각 데이터에 접근할 수 있다.

const CustomTooltip = ({ active, payload }) => {
  // ...
  const { price, createdAt, diff } = payload[0].payload;
  // ...
}

커스텀 컴포넌트 만들기

다음과 같은 Tooltip을 만들어보자.

  1. Tooltip의 제목은 00월 00일 가격 정보 로 설정
  2. Tooltip의 내용은 00,000원 (diff) 로 설정
  3. diff 가 양수면 00,000원 (▲ 0,000원), 음수면 00,000원 (▼ 0,000원) 로 설정
/** @jsxImportSource @emotion/react */
import { TooltipProps } from 'recharts';
import * as styles from './CustomTooltip.styles';

export type DiffType = 'increment' | 'decrement' | 'same';

const CustomTooltip: React.FC<TooltipProps<number, string>> = ({
  active,
  payload,
}) => {
  if (active && payload && payload.length) {
    // 각 데이터 정보 가져오기 
    const { price, createdAt, diff } = payload[0].payload;
    
    // Tooltip 제목 설정
    const title = `
      ${createdAt.substring(4, 6)}${createdAt.substring(6, 8)}일 
      가격 정보
    `;
    
    // Tooltip 내용 (가격) 설정
    const priceText = `${price.toLocaleString()}`;

    // Tooltip 내용 (diff) 설정
    let diffText = '';
    let diffType: DiffType = 'same';
    if (diff > 0) {
      diffText = `${diff.toLocaleString()}`;
      diffType = 'increment';
    } else if (diff < 0) {
      diffText = `${(-diff).toLocaleString()}`;
      diffType = 'decrement';
    } else {
      diffText = '( -- )';
    }

    return (
      <div css={styles.customTooltip}>
        <h3 css={styles.tooltipTitle}>{title}</h3>
        <div css={styles.tooltipContent}>
          <div css={styles.price}>{priceText}</div>
          <div css={styles.priceInfo(diffType)}>{diffText}</div>
        </div>
      </div>
    );
  } else {
    return null;
  }
};

export default CustomTooltip;

각 스타일은 emotion으로 지정해주었다. 또한 diffType에 따라 동적으로 스타일링을 구성하였다.

커스텀 컴포넌트 적용하기

<Tooltip content={<CustomTooltip />} />

References

profile
growth

0개의 댓글