[ChartJS / react-chartjs-2] mix형(bar/line) 차트 만들어보기 #4

2024. 10. 29. 16:59·FE

다른 차트 형태들은 예시가 많이 올라와있어서 비교적 예시가 적은 믹스형 차트에 대해 알아보고, 클릭 이벤트 등등을 적용해보고자 한다.

options와 그 외 기본적인 세팅들은 앞선 포스팅들을 참고해 주면 좋다!

 

먼저 예시 데이터를 어떤걸로 할지 고민하다가 npm trends 사이트의 차트를 응용해 보기로 하였다!

react vs vue - npm trends 링크 참고

 

 

npm trends 를 참고하여, react / vue에 대한 line 차트와 두 가지의 합계를 나타내는 총합계에 대한 bar 차트를 혼합하여 표현하고자 한다.

 

🍄 Mix 형 더미 데이터 넣기

기본적인 데이터 구조는 다음과 같이 잡았다.

import { Chart } from "react-chartjs-2";

import {
  ArcElement,
  BarElement,
  CategoryScale,
  Chart as ChartJS,
  Legend,
  LineElement,
  LinearScale,
  PointElement,
  Tooltip,
  registerables,
} from "chart.js";

ChartJS.register(
  ...registerables,
  LinearScale,
  CategoryScale,
  BarElement,
  PointElement,
  LineElement,
  Legend,
  Tooltip,
  ArcElement
);

const MixChartExample = () => {
  const react_dummy = [10, 10, 10, 10, 20, 20, 20, 20, 30, 30, 30, 30];
  const vue_dummy = [10, 30, 10, 10, 10, 20, 30, 30, 20, 20, 20, 30];
  const total_dummy = react_dummy.map((item, idx) => item + vue_dummy[idx]);
  const labels_dummy = new Array(12).fill(0).map((_, idx) => idx + 1 + "월");
  //chart data
  const mixData = {
    labels: labels_dummy,
    datasets: [
      {
        type: "line" as const,
        label: "React" as string,
        data: react_dummy,
        borderColor: "#DD5353",
        backgroundColor: "#DD5353",
        borderWidth: 2, // 선의 크기
        pointBorderWidth: 1, // point의 크기
        tension: 0.1, // line 차트일 경우 선의 휘어짐 정도
      },
      {
        type: "line" as const,
        label: "Vue" as string,
        data: vue_dummy,
        borderColor: "#5F9DF7",
        backgroundColor: "#5F9DF7",
        borderWidth: 2,
        pointBorderWidth: 1,
        tension: 0.1, // line 차트일 경우 선의 휘어짐 정도
      },
      {
        type: "bar" as const,
        label: "전체" as string,
        backgroundColor: "#ddd",
        data: total_dummy,
        borderColor: "#ddd",
        borderWidth: 2,
      },
    ],
  };

  return (
    <div>
      <Chart type="bar" data={mixData} />
    </div>
  );
};
export default MixChartExample;

 

data에 작성한 옵션들은 아래 링크들을 참고하여 추가할 수 있다.

point style 참고 문서 - ChartJS Line형 차트 옵션 참고 문서 - ChartJS

 

Line Chart | Chart.js

Line Chart A line chart is a way of plotting data points on a line. Often, it is used to show trend data, or the comparison of two data sets. const config = { type: 'line', data: data, };const config = { type: 'line', data: data, }; const labels = Utils.mo

www.chartjs.org

 

현재까지 잡힌 화면 ⭐️

 

🍄 options 추가해보기

1️⃣ labels의 간격을 최대 간격 지정해 주기 (maxTicksLimit)

실무에서 쓰다 보면, labels가 유동적인 경우가 있다. 예를 들어, 한 차트에서 3개월 - 1개월 - 일주일 간격의 데이터를 보여줘야 하는 상황에서 labels를 있는 그대로 표현해 준다면 화면에 내용이 너무 꽉 찰 수가 있다.

화면이 크다면 상관이 없지만, 작은 화면에서 3개월 치의 labels를 다 보여주기는 어려울 것이다!

chartJS에서는 이와 같은 옵션을 제공해주고 있다!! 다음과 같이 옵션을 채워줄 수 있다.

  const mixOptions = {
    scales: {
      x: {
        ticks: {
          maxTicksLimit: 6,
        },
      },
    },
  };
// 생략

    <div>
      <Chart type="bar" data={mixData} options={mixOptions}/>
    </div>

이미지를 보면, 최대 6개까지로 labels 가 고정되었단 것을 알 수 있다.

2️⃣ y축의 높이를 컨트롤해보자!

이번에는 한번 react_flex_dummy를 만들어보고, 해당 데이터를 react 쪽에 넣어보겠다.

  const react_flex_dummy = [
    10, 10, 1000, 10, 20, 200, 20, 20, 330, 30, 1130, 30,
  ];
// 생략 
  const mixData = {
    labels: labels_dummy,
    datasets: [
      {
        type: "line" as const,
        label: "React" as string,
        data: react_flex_dummy,
        ...

 

이와 같이 데이터 차이가 1000 이상 날 경우, 다음처럼 chart의 높이가 큰 차이를 내며 표시될 것이다.

 

보면... 최댓값이 너무너무 클 경우, 다른 데이터들이 바닥에 희미하게 보이는 것을 알 수 있다.. 😢

y축에 대해서도 ticks 옵션에 stepSize를 지정해 주면 되는데, labels와 다르게 data의 범위는 매우 유동적이기 때문에 특정 숫자를 지정해 주기 애매할 수가 있다...

data가 최대 몇부터 최소 몇까지 들어올지 모르기 때문이다!

☀️ 데이터의 max 값과 min 값을 활용하여 stepSize를 유동적으로 잡아주는 함수를 만들어보자!

데이터가 들어올 때마다, 데이터의 최댓값, 최솟값을 받아 간격을 잡아주는 함수를 만들어볼 수 있다.

const getStepSize = (min: number, max: number) => {
  const range = max - min; // 최댓값과 최솟값 간의 범위를 계산
  const interval = Math.ceil(range / 3); // 범위를 3등분하여 각 구간의 크기를 계산
  const exponent = Math.floor(Math.log10(interval)); // 각 구간의 크기에 대한 로그 값을 계산
  const factor = Math.pow(10, exponent); // 10의 거듭제곱을 통해 가장 가까운 10의 배수로 구간 크기를 정규화
  return Math.ceil(interval / factor) * factor;
};

 

total_dummy를 이용하여 min 값과 max 값을 정하여 적용해 주면 다음과 같이 react_flex_dummy와 react_dummy에 따라 y축의 간격이 조정되는 것을 볼 수 있다 ⭐️

 

react_flex_dummy 인 경우


 

react_dummy 인 경우

 

전체적인 코드는 다음과 같다! 다음 포스팅에서는 클릭 이벤트를 적용해 보겠다!

 

import { Chart } from "react-chartjs-2";

import {
  ArcElement,
  BarElement,
  CategoryScale,
  Chart as ChartJS,
  Legend,
  LineElement,
  LinearScale,
  PointElement,
  Tooltip,
  registerables,
} from "chart.js";
import { useMemo } from "react";

ChartJS.register(
  ...registerables,
  LinearScale,
  CategoryScale,
  BarElement,
  PointElement,
  LineElement,
  Legend,
  Tooltip,
  ArcElement
);

const MixChartExample = () => {
  const react_dummy = [10, 10, 10, 10, 20, 20, 20, 20, 30, 30, 30, 30];
  // const react_flex_dummy = [
  //   10, 10, 1000, 10, 20, 200, 20, 20, 330, 30, 1130, 30,
  // ];
  const vue_dummy = [10, 30, 10, 10, 10, 20, 30, 30, 20, 20, 20, 30];
  const total_dummy = react_dummy.map((item, idx) => item + vue_dummy[idx]);
  const labels_dummy = new Array(12).fill(0).map((_, idx) => idx + 1 + "월");

  // 최대,최소값을 구하는
  const min = useMemo(() => {
    return Math.min.apply(null, total_dummy);
  }, [total_dummy]);

  const max = useMemo(() => {
    return Math.max.apply(null, total_dummy);
  }, [total_dummy]);

  const mixOptions = {
    scales: {
      x: {
        ticks: {
          maxTicksLimit: 6,
        },
      },
      y: {
        ticks: {
          color: "#808080",
          stepSize: getStepSize(min, max),
        },
      },
    },
  };
  //chart data
  const mixData = {
    labels: labels_dummy,
    datasets: [
      {
        type: "line" as const,
        label: "React" as string,
        data: react_dummy,
        borderColor: "#DD5353",
        backgroundColor: "#DD5353",
        borderWidth: 2, // 선의 크기
        pointBorderWidth: 1, // point의 크기
        tension: 0.1, // line 차트일 경우 선의 휘어짐 정도
      },
      {
        type: "line" as const,
        label: "Vue" as string,
        data: vue_dummy,
        borderColor: "#5F9DF7",
        backgroundColor: "#5F9DF7",
        borderWidth: 2,
        pointBorderWidth: 1,
        tension: 0.1, // line 차트일 경우 선의 휘어짐 정도
      },
      {
        type: "bar" as const,
        label: "전체" as string,
        backgroundColor: "#ddd",
        data: total_dummy,
        borderColor: "#ddd",
        borderWidth: 2,
      },
    ],
  };

  return (
    <div>
      <Chart type="bar" data={mixData} options={mixOptions} />
    </div>
  );
};
export default MixChartExample;
const getStepSize = (min: number, max: number) => {
  const range = max - min; // 최댓값과 최솟값 간의 범위를 계산
  const interval = Math.ceil(range / 3); // 범위를 3등분하여 각 구간의 크기를 계산
  const exponent = Math.floor(Math.log10(interval)); // 각 구간의 크기에 대한 로그 값을 계산
  const factor = Math.pow(10, exponent); // 10의 거듭제곱을 통해 가장 가까운 10의 배수로 구간 크기를 정규화
  return Math.ceil(interval / factor) * factor;
};

'FE' 카테고리의 다른 글

[ReactFlow] 다이어그램 툴 만들기 #0  (3) 2024.10.30
[ChartJS / react-chartjs-2] 클릭이벤트 적용해보기 #5  (0) 2024.10.29
[ChartJS / react-chartjs-2] options 를 알아보기 #3  (0) 2024.10.29
[ChartJS / react-chartjs-2] 완벽한 반응형 차트를 구현해보자 #2  (0) 2024.10.29
[ChartJS / react-chartjs-2] 차트 라이브러리 설치, 기본 세팅하기 #1  (0) 2024.10.29
'FE' 카테고리의 다른 글
  • [ReactFlow] 다이어그램 툴 만들기 #0
  • [ChartJS / react-chartjs-2] 클릭이벤트 적용해보기 #5
  • [ChartJS / react-chartjs-2] options 를 알아보기 #3
  • [ChartJS / react-chartjs-2] 완벽한 반응형 차트를 구현해보자 #2
웹개발주인장
웹개발주인장
안녕하세요 :) velog와 티스토리를 동시에 운영중에 있습니다! https://velog.io/@hannah3406
  • 웹개발주인장
    Hannah
    웹개발주인장
  • 전체
    오늘
    어제
    • 분류 전체보기 (27)
      • FE (17)
      • BE (10)
      • 개발CS (0)
      • 잡담 (0)
      • 토이프로젝트 (0)
  • 인기 글

  • 태그

    GCP
    chartjs click
    트리구조
    HTTPS
    certbot
    Nginx
    pm2
    typscript
    chartjs
    react
    WINDOWING
    무한스크롤
    로드밸런서
    다이어그램
    infinite scroll
    Nextjs
    reactflow
    node.js
    google clioud platform
    react-chartjs-2
    scp명령어
    Google Cloud Platform
    nestjs
    서버
    chartjs2
    ssl 인증
    react-window
    gcp 도메인
    TypeScript
    배포
  • hELLO· Designed By정상우.v4.10.0
웹개발주인장
[ChartJS / react-chartjs-2] mix형(bar/line) 차트 만들어보기 #4
상단으로

티스토리툴바