React에서 차트 그리기 위해 Victory 라이브러리를 사용했습니다.
npm i victory
# or
yarn add victory
공식문서에 있는 퍼센트 막대 차트 예제입니다.
const myDataset = [
[
{ x: 'a', y: 1 },
{ x: 'b', y: 2 },
{ x: 'c', y: 3 },
{ x: 'd', y: 2 },
{ x: 'e', y: 1 },
],
[
{ x: 'a', y: 2 },
{ x: 'b', y: 3 },
{ x: 'c', y: 4 },
{ x: 'd', y: 5 },
{ x: 'e', y: 5 },
],
[
{ x: 'a', y: 1 },
{ x: 'b', y: 2 },
{ x: 'c', y: 3 },
{ x: 'd', y: 4 },
{ x: 'e', y: 4 },
],
]
const transformData = (dataset) => {
const totals = dataset[0].map((data, i) => {
return dataset.reduce((memo, curr) => {
return memo + curr[i].y
}, 0)
})
return dataset.map((data) => {
return data.map((datum, i) => {
return { x: datum.x, y: (datum.y / totals[i]) * 100 }
})
})
}
function Chart(){
const dataset = transformData(myDataset)
return (
<div>
<VictoryChart height={400} width={400} domainPadding={{ x: 30, y: 20 }}>
<VictoryStack colorScale={['black', 'blue', 'tomato']}>
{dataset.map((data, i) => {
return <VictoryBar data={data} key={i} />
})}
</VictoryStack>
<VictoryAxis dependentAxis tickFormat={(tick) => `${tick}%`} />
<VictoryAxis tickFormat={['a', 'b', 'c', 'd', 'e']} />
</VictoryChart>
</div>
)
}
먼저, 차트에 데이터를 x축, y축 데이터 형태로 전달해야 합니다. 그리고 퍼센트 막대 차트라서 퍼센트 데이터로 되어 있어야 합니다. transformData()
가 퍼센트 막대 차트에 맞는 데이터로 가공해서 반환합니다.
여기서 사용하는 Victory 컴포넌트에 간단히 소개하겠습니다.
위 차트는 결과물입니다.
프로젝트 코드는 여기서 확인할 수 있습니다. 아래는 그 결과물입니다.
공식문서에서 여러 옵션들 예제를 참고해 구현했습니다. 차트 범례는 VictoryLegend를 사용하지 않고 div태그로 따로 만들어서 사용했습니다. VictoryLegend로 구현했을 때 제가 원하는 위치로 이동이 자유롭지 않아서 직접 구현했습니다. 여기서 제일 고민했던 것은 어떻게 가독성 있게 원본 데이터를 차트에 맞는 데이터로 가공할 수 있을까였습니다. 함수형 프로그래밍을 사용했습니다. lodash에서 chain을 이용해 선언적으로 함수들을 사용했습니다. 그 결과는 프로젝트 코드를 제공하는 링크에서 transformData()
를 보시면 됩니다.