더 알아보기
이전 게시물에서 말했듯이 Chart.js 라이브러리를 사용하여 도넛 차트를 구현했다.
1. Chart.js 라이브러리를 설치한다.
npm install --save react-chartjs-2 chart.js
or
yarn add react-chartjs-2 chart.js
2. Chart.js 파일을 생성하고, 구현하고자 하는 차트의 기존 코드를 복붙한다.
코드
더보기
import { Doughnut } from "react-chartjs-2";
const expData = {
labels: ["A", "B", "C", "D", "F"],
datasets: [
{
labels: ["A", "B", "C", "D", "F"],
data: [20, 20, 20, 20, 20],
borderWidth: 0, // 차트별 border CSS
hoverBorderWidth: 0,
backgroundColor: ["#E1E1E1", "#038CFF", "#90F9A0", "#21F2A5", "#00DCEC"],
fill: false,
},
],
};
const Chart = () => {
return (
<div style={{ width: "300px" }}>
<Doughnut
options={{
interaction: {
intersect: false,
mode: "index",
},
legend: {
position: "right",
},
}}
data={expData}
height={120}
/>
</div>
);
};
3. 이때 "Error: "arc" is not a registered element." 오류가 발생하는 데, 상단에 아래 import를 추가 해주면 된다.
import "chart.js/auto";
4. tooltip이나 chart를 커스텀 할 때는 Chart.js 공식문서 > Samples의 예제들을 많이 참고했다.
전체 코드
더보기
// 공식문서 https://www.chartjs.org/docs/latest/samples/legend/html.html
import "chart.js/auto";
// 출처 https://stackoverflow.com/questions/70098392/react-chartjs-2-with-chartjs-3-error-arc-is-not-a-registered-element
import { Doughnut } from "react-chartjs-2";
// 출처 https://dipsiiiiiiiiii.com/2019/11/03/1%EC%B0%A8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-react%EC%97%90%EC%84%9C-chart-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0/
// Chart 데이터
const expData = {
labels: ["A", "B", "C", "D", "F"],
datasets: [
{
labels: ["A", "B", "C", "D", "F"],
data: [5290500, 14103000, 4282000, 3288000, 3036500],
borderWidth: 0, // 차트별 border CSS
hoverBorderWidth: 0,
backgroundColor: ["#E1E1E1", "#038CFF", "#90F9A0", "#21F2A5", "#00DCEC"],
fill: false,
},
],
};
// Chart > ToolTip 커스텀
const getOrCreateTooltip = (chart) => {
let tooltipEl = chart.canvas.parentNode.querySelector("div");
if (!tooltipEl) {
tooltipEl = document.createElement("div");
tooltipEl.style.background = "#FFFFFF 0% 0% no-repeat padding-box";
tooltipEl.style.borderRadius = "10px";
tooltipEl.style.color = "#000000";
tooltipEl.style.opacity = 1;
tooltipEl.style.pointerEvents = "none";
tooltipEl.style.position = "absolute";
tooltipEl.style.transform = "translate(-50%, 0)";
tooltipEl.style.transition = "all .1s ease";
const table = document.createElement("table");
table.style.margin = "0px";
tooltipEl.appendChild(table);
chart.canvas.parentNode.appendChild(tooltipEl);
}
return tooltipEl;
};
const externalTooltipHandler = (context) => {
// Tooltip Element
const { chart, tooltip } = context;
const tooltipEl = getOrCreateTooltip(chart);
// Hide if no tooltip
if (tooltip.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set Text
if (tooltip.body) {
const titleLines = tooltip.title || [];
const bodyLines = tooltip.body.map((b) => b.lines);
const tableHead = document.createElement("thead");
titleLines.forEach((title) => {
const tr = document.createElement("tr");
tr.style.borderWidth = 0;
const th = document.createElement("th");
th.style.borderWidth = 0;
const text = document.createTextNode(title);
th.appendChild(text);
tr.appendChild(th);
tableHead.appendChild(tr);
});
const tableBody = document.createElement("tbody");
bodyLines.forEach((body, i) => {
const colors = tooltip.labelColors[i];
const span = document.createElement("span");
span.style.background = colors.backgroundColor;
span.style.borderColor = colors.borderColor;
span.style.borderWidth = "2px";
span.style.marginRight = "10px";
span.style.height = "10px";
span.style.width = "10px";
span.style.display = "inline-block";
const tr = document.createElement("tr");
tr.style.backgroundColor = "inherit";
tr.style.borderWidth = 0;
const td = document.createElement("td");
td.style.display = "block";
td.style.width = "100px";
td.style.textAlign = "center";
// tooltip text 커스텀
const text = document.createTextNode(`${body[0].split(":")[0]}`);
const text2 = document.createTextNode(`${body[0].split(":")[1]}원`);
td.appendChild(span);
td.appendChild(text);
td.appendChild(text2);
tr.appendChild(td);
tableBody.appendChild(tr);
});
const tableRoot = tooltipEl.querySelector("table");
// Remove old children
while (tableRoot.firstChild) {
tableRoot.firstChild.remove();
}
// Add new children
tableRoot.appendChild(tableHead);
tableRoot.appendChild(tableBody);
}
const { offsetLeft: positionX, offsetTop: positionY } = chart.canvas;
// Display, position, and set styles for font
tooltipEl.style.background = "#FFFFFF 0% 0% no-repeat padding-box";
tooltipEl.style.boxShadow = "0px 0px 10px #ADADAD40";
tooltipEl.style.borderRadius = "10px";
tooltipEl.style.font = "normal normal normal 14px/16px Pretendard";
tooltipEl.style.letterSpacing = "-0.35px";
tooltipEl.style.color = "#000000";
tooltipEl.style.opacity = 1;
tooltipEl.style.left = positionX + tooltip.caretX + "px";
tooltipEl.style.top = positionY + tooltip.caretY + "px";
tooltipEl.style.font = tooltip.options.bodyFont.string;
tooltipEl.style.padding =
tooltip.options.padding + "px " + tooltip.options.padding + "px";
};
const Chart = () => {
return (
<div style={{ width: "300px" }}>
<Doughnut
options={{
interaction: {
intersect: false,
mode: "index",
},
legend: {
position: "right",
},
plugins: {
// 카테고리 커스텀
legend: {
display: false,
},
// 제목 커스텀
title: {
display: false,
text: "Chart.js Line Chart - External Tooltips",
},
// 툴팁 커스텀
tooltip: {
enabled: false,
position: "nearest",
external: externalTooltipHandler,
},
},
}}
data={expData}
height={120}
/>
</div>
);
};
export default Chart;
'더 알아보기 > 기능' 카테고리의 다른 글
[react-datepicker] 달력 만들기_v2 (0) | 2022.04.15 |
---|---|
[React] 부트스트랩 페이징 구현하기 (0) | 2022.04.11 |
차트(Chart) 라이브러리 (0) | 2022.04.06 |
[react-datepicker] 달력 만들기_v1 (0) | 2022.03.29 |
[React] 다음 주소 API 적용하기 (0) | 2022.03.28 |
댓글