프로젝트 과정 기록

[JS] Chartjs 막대그래프 그리기 (별점 분포 차트)

페블_ 2023. 8. 3. 21:07

별점들을 표시하고 최빈값을 다른 색으로 표시하는 차트를 그릴 것이다.

 

1. 준비물

CDN 방식으로 라이브러리 불러오기

<script src="https://cdn.jsdelivr.net/npm/chart.js" defer></script>

 

script 부분

<script src="https://cdn.jsdelivr.net/npm/chart.js" defer></script>
<script src="index.js" defer></script>
<link href="style.css" rel="stylesheet" />

body 부분

<div class="chart-box">
  <canvas id="myChart"></canvas>
  <div id="average"></div>
</div>

 

2. 크키 지정 (반응형)

chartjs 옵션을 따로 설정할 필요 없이 차트 canvas를 div로 감싸고, 그 div에 max-width로 크기를 지정하면 된다.

.chart-box {
  margin: auto;
  max-width: 800px;
}

#average {
  margin-top: 30px;
  text-align: center;
}

 

3. 차트 그리기

const ratings = [
  { stars: 1, count: 100 },
  { stars: 2, count: 230 },
  { stars: 3, count: 700 },
  { stars: 4, count: 500 },
  { stars: 5, count: 520 },
];

const ctx = document.getElementById('myChart');

new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ratings.map((item) => `${item.stars}점`),
    datasets: [
      {
        label: '별점 분포',
        data: ratings.map((item) => item.count),
        borderWidth: 1,
      },
    ],
  },
  options: {
    scales: {
      x: {
        grid: {
          display: false, // bar 구분하는 격자 숨김
        },
      },
      y: {
        beginAtZero: true,
        grid: {
          display: false, // 눈금 격자 숨김
        },
        ticks: {	// tick이란 y축에서 100, 200 숫자 표시하는 부분. 보이지 않게 한다.
          display: false,
          callback: function (value, index, values) {
            return value.toLocaleString();
          },
        },
      },
    },
  },
});

 

4. 별점 평균 계산

const totalStars = ratings.reduce(
  (acc, curr) => acc + curr.stars * curr.count,
  0
);
const totalCount = ratings.reduce((acc, curr) => acc + curr.count, 0);
const average = (totalStars / totalCount).toFixed(1);
const averageElement = document.getElementById('average');
averageElement.innerHTML = `평균 ${average}점`;

 

여기까지 결과물

 

 

5. 막대 너비 조절 및 배경색 지정

최빈값에만 다른 색을 지정하기 위해 먼저 최빈값을 구한다.

const maxCount = Math.max(...ratings.map((item) => item.count));

 

data에 다음과 같이 backgroundColor, barPercentage, categoryPercentage 속성을 추가해준다.

  • barPercentage - 1로 설정하면 막대의 너비가 약간 넓어짐
  • categoryPercentage: 막대가 완전히 붙도록 더 커짐
data: {
    labels: ratings.map((item) => `${item.stars}점`),
    datasets: [
      {
        label: '별점 분포',
        data: ratings.map((item) => item.count),
        borderWidth: 1,
        backgroundColor: ratings.map((item) =>
          item.count === maxCount ? '#fcce03' : '#fcdb03'
        ),
        borderColor: '#fcba03',
        barPercentage: 1,
        categoryPercentage: 1,
      },
    ],
  },

backgroundColor에서 최빈값과 동일한 값에는 다른 색을 표시해준다.

borderColor는 주황색보다 약간 더 진한 주황색을 설정해 bar가 구별가게 해준다.