Software Frontend/react & Javascript

자바스크립트를 이용해서 차트를 구현하고 PDF로 다운로드 Chart js, jspdf

light_meal 2021. 8. 28. 17:29
728x90

차트를 구현해보자 Chart js

차트 만드는 라이브러리로 어떤 것이 좋을까? 여러가지 비교하며 고르고 골라 사용했던 Chart js를 정리해보려고 한다.

이 라이브러리를 고른 이유는 다른 라이브러리와 비교했을 때 차이점은 다음과 같다

  1. 깔끔하다.
  2. 예쁘다.
  3. 정말 다양한 차트 종류를 구현 할 수 있도록 제공
  4. 가장 중요한 점은 해당 홈페이지에서 꽤 자세한 설명이 작성되어 있어 좋았다.

우선 당연하게도 Chart js를 사용하려면 해당 라이브러리를 받아야 하는데 CDN 방식으로 받아 사용하려 한다.

솔직히 Chart js 해당 페이지에 다양한 튜토리얼이 많아서 따로 블로그에 들어가서 공부하지 않고 해당 홈페이지에 들어가서 참고만 해봐도 될 정도이다.

Chart js 사이트 : https://www.chartjs.org/

  • 확인해본 결과 내가 이전에 사용했을 때보다도 더 좋은 예제들이 많이 추가되었음을 확인했다. 꾸준히 보완하고 발전하는 라이브러리라고 생각한다.
  • 위와 같은 이유로 인해 Chart Js에 사용법에 대해서는 간단히 작성하려 한다.

라이브러리에 대한 CDN 주소는 아래와 같으며 현재 3.5.1이 최신 버전이다.

Chart js CDN : https://www.jsdelivr.com/package/npm/chart.js

<script src="[https://cdn.jsdelivr.net/npm/chart.js@3.5.1/dist/chart.min.js](https://cdn.jsdelivr.net/npm/chart.js@3.5.1/dist/chart.min.js)"></script>

우선 기본은 다음과 같다

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Chart js</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@3.5.1/dist/chart.min.js"></script>
</head>
<body>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
        let ctx = document.getElementById('myChart').getContext('2d');
        let myChart = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
                datasets: [{
                    label: '# of Votes',
                    data: [12, 19, 3, 5, 2, 3],
                    backgroundColor: [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(255, 206, 86, 0.2)',
                        'rgba(75, 192, 192, 0.2)',
                        'rgba(153, 102, 255, 0.2)',
                        'rgba(255, 159, 64, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255, 99, 132, 1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)',
                        'rgba(75, 192, 192, 1)',
                        'rgba(153, 102, 255, 1)',
                        'rgba(255, 159, 64, 1)'
                    ],
                    borderWidth: 1
                }]
            },
            options: {
                scales: {
                    y: {
                        beginAtZero: true
                    }
                }
            }
        });

</script>
</body>
</html>

이렇게 사용할 경우 문제는 태그에서 width와 height를 설정했지만 적용되지 않아 전체 화면으로 나타나게 된다.

이 문제를 해결하기 위해서는 options에 responsive: false 를 추가하거나

<div><canvas></div>

태그 안에서 작성하면 해당 태그의 크기 만큼만 커진다.

그렇다면 위처럼 처음부터 데이터를 세팅해서 사용해야 하나?

위와 같은 궁금증이 생길 것이다.

왜냐? 보통 차트를 제공해주는데 있어서 딱 정해진 데이터만을 제공하지 않기 때문이다.

예를 들어 판매한 금액의 정산 내역을 확인함에 있어서 1개월치 2개월치 3개월치 데이터와 같이 다양한 변수가 존재하기 때문에 차트의 모양은 바뀌어야 할 것이다.

이를 해결하기 위해선 자바스크립트에 대해 이해를 해야 하는데, 초보였던 나로서는 뭐 어떻게 하라는거야? 하면서 열심히 찾아보았고 JSONArray()의 방법을 이해하고 사용이 가능했다.

그렇기 때문에 Javascript에서 JSON과 Array()의 구조, 사용 방법을 공부하기 바란다.

그냥 간단하게 예시만 보여주자면 다음과 같이 선언해서 사용하면 되겠다.

// 따로 변수를 선언해서 사용해야 한다.
let myChart ;
// 함수를 선언줘서 이용한다.
// 차트 추가하기
function addData(myChart, data) {
    // 매개변수로 myChart를 넘겨주면
    // myChart 객체의 data 의 datasets에 data를 넣어(push)준다라는 뜻이다.
  myChart.data.datasets.push(data);
    // chart update를 해주어야 해당 사항이 반영이 된다.
  myChart.update();
}
// 차트 삭제하기
function removeData(myChart,delData) {
    // 위와 마찬가지로 삭제는 splice로 삭제해주면 되겠다.
  myChart.data.datasets.splice(delData,1);
  myChart.update();
}

// 이렇게 함수로 선언해서 사용하지 않고 직접 사용해도 무방하다.

let ctx = document.getElementById('myChart').getContext('2d');
myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            y: {
                beginAtZero: true
            }
        }
    }
});

맨 위에서 Chart Js 라이브러리는 홈페이지에서 충분히 설명해주고 있기 때문에 여기까지만 설명하겠다.


구현한 차트를 PDF 파일로 다운로드 받기 jsPDF

위 라이브러리를 사용한 이유는 chart js로 구현하여 pdf 다운로드에 적용하고자 찾았으나 해당 방법만이 가능했다.

해당 라이브러리는 https://github.com/MrRio/jsPDF?utm_source=cdnjs&utm_medium=cdnjs_link&utm_campaign=cdnjs_library 이 주소에서 참고할 수 있다.

<script src='https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.3/jspdf.debug.js'></script>

자바스크립트 전문가는 아니지만 깃 허브 페이지에 작성되어 있는 사용 방법은 NPM으로 라이브러리를 다운 받아 사용하는 것으로 보인다.

나는 자바스크립트를 위 페이지에 작성된 방법으로 사용할 수 없어서 다음과 같이 사용했다.

그렇기에 버전이 옛날 버전이다.

더 좋은 방법이 있다면 꼭 찾아보기 바란다.

내가 이해한 바로는 새로운 캔버스를 만들어서 해당 캔버스에 차트 캔버스를 넣어서 다운로드 하는 것으로 이해했다.

$( ()=>{
  //pdf 다운로드 누르면 실행
  $('#pdfDown').click( () => {
    // 페이지의 크기를 구한다.
    var reportPageHeight = $('#chartContainer').innerHeight();
    var reportPageWidth = $('#chartContainer').innerWidth();

    // 캔버스 개체를 만든다.
    var pdfCanvas = $('<canvas />').attr({
        id: "canvaspdf",
        width: reportPageWidth,
        height: reportPageHeight
      });

    // 캔버스 포지션을 정한다.
    var pdfctx = $(pdfCanvas)[0].getContext('2d');
    var pdfctxX = 0;
    var pdfctxY = 0;
    var buffer = 100;

      // for each chart.js chart
    $("canvas").each(function(index) {
      // 차트의 크기를 구한다.
      var canvasHeight = $(this).innerHeight();
      var canvasWidth = $(this).innerWidth();

      // 새로운 캔버스 안에 넣는다.
      pdfctx.drawImage($(this)[0], pdfctxX, pdfctxY, canvasWidth, canvasHeight);
      pdfctxX += canvasWidth + buffer;

      if (index % 2 === 1) {
        pdfctxX = 0;
        pdfctxY += canvasHeight + buffer;
      }
    });

    // pdf 객체를 생성하여 넣는다.
    var pdf = new jsPDF('l', 'pt', [reportPageWidth, reportPageHeight]);
    pdf.addImage($(pdfCanvas)[0], 'PNG', 0, 0);

    // pdf 다운로드
    pdf.save('PDF파일 이름.pdf');
    alert('PDF파일 이름 PDF 파일 다운로드가 실행되어 다운로드 폴더에 생성됩니다.');
});

다운로드 된 pdf 파일

이렇게 다운 받게 되면 해당 클라이언트의 <다운로드>폴더에 자동으로 다운된다.

문제점으로 다음과 같이 작게 나온다.

그렇다면 어떻게 크게 다운로드 받을 수 있을까?

구현해보지는 않았지만 다른 홈페이지들에서 활용하는 방법을 보면 새로운 페이지를 띄어서 그 페이지에 풀 사이즈로 출력 되도록 한 뒤 pdf 다운을 구현하면 될 것이라 생각한다.

프로젝트를 진행하며 급하게 알아보며 만들었던 터라 다소 이해하지 않고 만든 부분이 있어 설명이 부족했을 수도 있을 것이다.

100% 이해하는 것이 가장 좋지만 우선 다른 사람이 만든 것을 보고 따라 만들어보는 것도 도움이 될 것이라 생각한다.

 

나는 프로젝트에서 다음과 같이 구현했다.

이 글을 읽은 분들께 도움이 되었길 바랍니다.

이상입니다.

728x90