본문 바로가기
Languages/Vue.js

Vue.js와 Chart.js를 이용하여 아름다운 차트 만들기

by chuckolet 2018. 11. 25.

차트는 모던 웹사이트와 어플리케이션의 중요한 부분입니다. 차트는 텍스트로 쉽게 표현할 수 없는 정보를 쉽게 전달 할 수 있도록 도와주며 일반적으로 텍스트 형태일 때는 이해하기 어려운 데이터를 이해하고 읽기 쉽게 만들어줍니다. 

 

이 글에서는 Chart.js와 Vue.js의 도움을 받아 다양한 타입의 차트 형태로 데이터를 표현해볼 것 입니다.

Chart.js는 개발자와 디자이너들에게 HTML5 canvas 엘리먼트를 이용하여 다양한 종류의 차트를 그릴 수 있도록 해주는 간단하지만 유연한 자바스크립트 차트 라이브러리입니다.

 

Vue.js는 우리가 차트 예제를 시연하기 위해 Chart.js와 함께 사용할 progressive 자바스크립트 프레임워크입니다. 또한 우리는 우리가 만들 데모 프로젝트를 위한 발판으로 vue-cli를 사용할 것입니다. vue-cli는 간단한 CLI(command-line-interface)로 앱이 만들어질 수 있는 다양한 템플릿을 지원하지만 우리 앱을 만들기 위해서 우리는 이 중 webpack 템플릿을 이용할 것입니다.

다양한 차트들

Vue.js에 구축 된 다양한 JavaScript 차트 라이브러리와 차트 wrapper가 있지만, 이 글은 Chart.js에 중점을 둘 것이기 때문에 Chart.js에 대한 Vue wrapper 중 vue-chartsvue-chartjsvue-chartkick 이 세가지를 알아보도록 하겠습니다.

vue-cli로 프로젝트 준비

우선 아래 명령어로 vue-cli를 설치하세요.
다 됐으면 이제 webpack을 이용하여 my-project라는 이름의 데모 프로젝트를 만들어봅시다.
vue init webpack my-project
 
 
그리고 아래 명령어로 차트 라이브러리를 다운 받읍시다.
npm install chart.js chartkick hchs-vue-charts vue-chartjs vue-chartkick
 
팁: npm 5 이상 버전부터는 --save 플래그를 사용하지 않아도 자동으로 패키지가 package.json에 저장됩니다. 참고

이제 우리가 필요한 모든 dependencies와 Chart.js Vue wrapper를 설치했습니다. 아래 명령어로 테스트 해봅시다.

npm run dev
 
웹브라우저 주소창에 localhost:8080으로 접속했을 때 아래와 같은 창이 뜨면 제대로 설치된 것 입니다.

Routes 추가

다음으로 할 일은 각 wrapper에 대한 차트를 볼 수 있는 여러 경로를 만드는 것 입니다. 최종적으로 우리는 vue-charts wrapper로 만든 차트를 보여줄 /charts 라우트, vue-chartjs wrapper로 만든 차트를 보여줄 /chartjs, 마지막으로 vue-chartkick wrapper로 만든 차트를 보여줄 /chartkick를 만들 것 입니다. 앱의 router 폴더로 가서 index.js를 열어서 안의 내용을 아래 내용으로 교체해봅시다.

 

index.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/views/Home'
import VueChartJS from '@/views/VueChartJS'
import VueChartKick from '@/views/VueChartKick'
import VueCharts from '@/views/VueCharts'


Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/chartjs',
      name: 'VueChartJS',
      component: VueChartJS
    },
    {
      path: '/chartkick',
      name: 'VueChartKick',
      component: VueChartKick
    },
    {
      path: '/charts',
      name: 'VueCharts',
      component: VueCharts
    }
  ]
})
 
 
위 코드에 대해 설명하기 전에 우선 src/components/ 폴더에 다음 vue 파일들을 만들어 줍니다.
 
  • VueChartJS.vue
  • VueChartKick.vue
  • VueCharts.vue

이제 위의 코드에 대해 설명하자면, 

우리는 우선 위에서 만든 Vue components에서 몇몇 파일을 import 했습니다. Components는 Vue의 가장 강력한 기능 중 하나입니다. 기본 HTML 요소를 확장하여 재사용 가능한 코드를 캡슐화하는 데 도움이됩니다. 좀 더 깊은 수준에서보면 components는 Vue 컴파일러가 behavior를 attach하는 커스텀 요소입니다. 
마지막 부분에는 다른 차트를 표시하는 데 필요한 여러 페이지를 제공하는 경로와 구성 요소를 정의했습니다.

Home Component

Home component는 default(/) 라우터로 사용됩니다. 우리는 Home component를 새로 만들거나, 아니면 간단히 기존의 자동 생성된 HelloWorld.vue 파일의 이름을 Home.vue로 바꾸고 아래 내용으로 바꿔주면 됩니다.
 
Home.vue
<template>
  <section class="hero is-success is-fullheight">
    <div class="hero-body">
      <div class="container">
        <h1>Creating Beautiful Charts Using Vue.js Wrappers For Chart.js</h1>
        <ul>
          <li><router-link to="/chartjs">vue-chartjs</router-link></li>
          <li><router-link to="/charts">vue-charts</router-link></li>
          <li><router-link to="/chartKick">vue-chartKick</router-link></li>
        </ul>
      </div>
    </div>
  </section>
</template>

<script>
export default {
  name: 'home'
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .home {
    display: flex;
    align-items: center;
    align-content: center;
    justify-content: center;
  }
  h1, h2 {
    font-weight: normal;
  }
  ul {
    list-style-type: none;
    padding: 0;
  }
  li {
    display: inline-block;
    margin: 0 10px;
  }
  a {
    color: #42b983;
    text-decoration: underline;
  }
</style>​

 

Bulma 프레임워크 추가

시작하기 전에 Bulma CSS 프레임워크를 추가해줍시다. 이 프레임워크를 이용하면 CSS에 관한 작업들이 더 쉬워 집니다.
앱의 루트 디렉토리에서 index.html 파일을 열고 아래 코드를 <head></head> tag 안에 넣어줍시다.
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.2/css/bulma.min.css" rel="stylesheet">
이제 본격적으로 chart를 만들어 봅시다.

VueChart.js로 차트 만들기

vue-chartjs는 재사용 가능한 차트 component를 쉽게 만들 수있는 Chart.js wrapper입니다. 재사용 가능성(Reusability)이란 베이스 차트 클래스를 가져 와서 custom한 component를 만들도록 확장 할 수 있는 것을 의미합니다.
vue-chartjs는 Line Chart, Bar Chart, Bubble Chart 그리고 Reactivity(데이터 세트가 변경 될 때마다 차트가 업데이트 됨)를 보여주는 Bar chart 이렇게 4가지 유형의 차트를 만들 수 있습니다. 우선 다음으로 진행하기 전에 이 파일들을 src/components/ 폴더 안에 생성해주세요.
  • LineChart.vue
  • BarChart.vue
  • BubbleChart.vue
  • Reactive.vue

Line Chart

Line 차트를 만들기 위해, Line 차트를 render하는 컴포넌트를 만들어 보겠습니다. src/components 안의 LineChart.vue를 열고 아래 내용을 입력해주세요.
LineChart.vue
<script>
  //Importing Line class from the vue-chartjs wrapper
  import {Line} from 'vue-chartjs'
  //Exporting this so it can be used in other components
  export default { 
    extends: Line,
    data () {
      return {
        datacollection: {
          //Data to be represented on x-axis
          labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 
                    'August', 'September', 'October', 'November', 'December'], 
          datasets: [
            {
              label: 'Data One',
              backgroundColor: '#f87979',
              pointBackgroundColor: 'white',
              borderWidth: 1,
              pointBorderColor: '#249EBF',
              //Data to be represented on y-axis
              data: [40, 20, 30, 50, 90, 10, 20, 40, 50, 70, 90, 100]
            }
          ]
        },
        //Chart.js options that controls the appearance of the chart
        options: {
          scales: {
            yAxes: [{
              ticks: {
                beginAtZero: true
              },
              gridLines: {
                display: true
              }
            }],
            xAxes: [ {
              gridLines: {
                display: false
              }
            }]
          },
          legend: {
            display: true
          },
          responsive: true,
          maintainAspectRatio: false
        }
      }
    },
    mounted () {
      //renderChart function renders the chart with the datacollection and options object.
      this.renderChart(this.datacollection, this.options)
    }
  }
</script>
 
위 코드가 뭘 하는지 의논해봅시다. 첫번째로 우리는 우리가 필요로 하는 차트 클래스(여기서는 Line)를 vue-chart.js에서 import 했고 외부에서 사용할 수 있도록 export 했습니다.
data 프로퍼티는 우리가 Line 차트를 그리기 위해 필요한 모든 정보를 가지고 있는 datacollection 객체를 가지고 있습니다. datacollection은 x축 위에서 표현될 labels, y축 위에서 표현 될 datasets, 그리고 차트의 외관을 컨트롤 할 options 같은 Chart.js 설정을 갖고 있습니다.
mounted함수는 datacollection과 options 객체를 파라메터로 보내서 차트를 render하는 renderChart() 함수를 부릅니다. 
 
다음으로 VueChartJS.vue 파일을 열어서 아래 내용을 입력해줍니다.
VueChartJS.vue
<template>
  <section class="container">
    <ul>
      <li><router-link to="/">Home</router-link></li>
      <li><router-link to="/chartjs">vue-chartjs</router-link></li>
      <li><router-link to="/charts">vue-charts</router-link></li>
      <li><router-link to="/chartKick">vue-chartKick</router-link></li>
    </ul>
    <h1>Demo examples of vue-chartjs</h1>
    <div class="columns">
      <div class="column">
        <h3>Line Chart</h3>
        <line-chart></line-chart>
      </div>
      <div class="column">
        <h3>Bar Chart</h3>
        <!--Bar Chart example-->
      </div>
    </div>
    <div class="columns">
      <div class="column">
        <h3>Bubble Chart</h3>
        <!--Bubble Chart example-->
      </div>
      <div class="column">
        <h3>Reactivity - Live update upon change in datasets</h3>
        <!--Reactivity Line Chart example-->
      </div>
    
    </div>
  </section>
</template>

<script>
  import LineChart from '@/components/LineChart'
  import BarChart from '@/components/BarChart'
  import BubbleChart from '@/components/BubbleChart'
  import Reactive from '@/components/Reactive'

  export default {
    name: 'VueChartJS',
    components: {
      LineChart,
      BarChart,
      BubbleChart,
      Reactive
    },

  }
</script>

<style scoped>
  ul {
    list-style-type: none;
    padding: 0;
  }

  li {
    display: inline-block;
    margin: 0 10px;
  }

  a {
    color: #42b983;
  }
</style>
 
VueChartJS.vue 파일은 HTML 코드를 포함하는 있는 template, Javascript 코드를 포함하는 script 그리고 CSS 코드를 포함하는 style 섹션을 포함합니다.
 
template 섹션에서, 우리는 다른 페이지로 가는 링크를 보여주는 메뉴를 나타내는 코드를 짰습니다. 그 후에 우리는 Bulma에서 두 2열 2행을 가진 레이아웃을 만드는 column 클래스를 사용했습니다. 또 우리는 script 섹션에 생성될 line-chat 컴포넌트를 만들었습니다.
 
script 섹션에서 우리는 우리가 미리 만ㄴ .vue 파일을 import하고 이를 components 객체에 reference 시켰습니다. 이는 우리가 앞으로 이 파일들을 line-chart, bar-chart, bubble-chart, reactive 같은 HTML 코드로 사용할 수 있다는 것과 같은 말입니다.
 
이제 여러분이 npm run dev를 하고 /chartjs로 이동하면 아래 그림처럼 Line Chart가 페이지에 출력될 겁니다.

Bar Chart

다음 차트로 Bar Chart를 만들어봅시다. src/components 폴더의 BarChart.vue를 열고 아래 코드를 입력해봅시다.
 
BarChart.vue
<script>
//Importing Bar class from the vue-chartjs wrapper
import {Bar} from 'vue-chartjs'
//Exporting this so it can be used in other components
export default {
  extends: Bar,
  data() {
    return {
      datacollection: {
        //Data to be represented on x-axis
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
        datasets: [
          {
            label: 'Data One',
            backgroundColor: '#f87979',
            pointBackgroundColor: 'white',
            borderWidth: 1,
            pointBorderColor: '#249EBF',
            //Data to be represented on y-axis
            data: [40, 20, 30, 50, 90, 10, 20, 40, 50, 70, 90, 100]
          }
        ]
      },
      //Chart.js options that controls the appearance of the chart
      options: {
        scales: {
          yAxes: [{
            ticks: {
              beginAtZero: true
            },
            gridLines: {
              display: true
            }
          }],
          xAxes: [ {
            gridLines: {
              display: false
            }
          }]
        },
        legend: {
            display: true
          },
        responsive: true,
        maintainAspectRatio: false
      }
    }
  },
  mounted() {
    //renderChart function renders the chart with the datacollection and options object.
    this.renderChart(this.datacollection, this.options)
  }
}
</script>​
위 코드는 LineChart.vue와 유사하게 동작할 겁니다. 딱 하나 다른 점은 Line 클래스 대신 Bar 클래스가 import, extend 되었다는거죠.
Bar 차트를 보기 전에 하나 더 해야할 일이 있는데, 그건 바로 VueChartJS.vue를 수정하는 겁니다. <!--Bar Chart example--> 부분을 <bar-chart></bar-chart>로 바꿔줍시다. 이렇게 단순히 <bar-chart>라고 HTML 템플릿 안에 적어주는 것 만으로 bar-chart 컴포넌트를 불러올 수 있습니다.

Bubble Chart

Bubble 차트를 만들기 위해 BubbleChart.vue 컴포넌트 파일을 열고 아래처럼 수정해줍니다.
참고: bubble 차트는 3차원 함수(x, y, r)를 이용하여 bubble, circle을 만듭니다. x는 가로축, y는 세로축, r은 각 bubble의 크기를 표현하는데 사용됩니다.
 
BubbleChart.vue
<script>
  //Importing Bubble class from the vue-chartjs wrapper
  import {Bubble} from 'vue-chartjs'
  //Exporting this so it can be used in other components
  export default{
    extends: Bubble,
    data () {
      return {
        datacollection: {
          //Data to be represented on x-axis
          labels: ['Data'],
          datasets: [
            {
              label: 'Data One',
              backgroundColor: '#f87979',
              pointBackgroundColor: 'white',
              borderWidth: 1,
              pointBorderColor: '#249EBF',
              //Data to be represented on y-axis
              data: [
                {
                  x: 100,
                  y: 0,
                  r: 10
                },
                {
                  x: 60,
                  y: 30,
                  r: 20
                },
                {
                  x: 40,
                  y: 60,
                  r: 25
                },
                {
                  x: 80,
                  y: 80,
                  r: 50
                },
                {
                  x: 20,
                  y: 30,
                  r: 25
                },
                {
                  x: 0,
                  y: 100,
                  r: 5
                }
              ]
            }
          ]
        },
        //Chart.js options that controls the appearance of the chart
        options: {
          scales: {
            yAxes: [{
              ticks: {
                beginAtZero: true
              },
              gridLines: {
                display: true
              }
            }],
            xAxes: [ {
              gridLines: {
                display: false
              }
            }]
          },
          legend: {
            display: true
          },
          responsive: true,
          maintainAspectRatio: false
        }
      }
    },
    mounted () {
    //renderChart function renders the chart with the datacollection and options object.
      this.renderChart(this.datacollection, this.options)
    }
  }
</script>

위의 코드 역시 LineChart.vue나 BarChart.vue와 유사합니다. 차이는 Line이나 Bar 클래스 대신 Bubble 클래스를 import, export한 것, datasets 객체가 x, y, z라는 다른 변수를 갖고 있는 것입니다.

 

Reactive Chart

우리가 vue-chartjs로 만들어 볼 마지막 예제는 dataset이 변경되었을 때마다 자동으로 업데이트되는 차트입니다. 주의해서 알아두어야 할 점은 Chart.js는 일반적으로 지원하지 않지만, vue-chartjs는 두 가지 mixin을 사용할 수 있다는 것입니다.
  • reactiveProp
  • reactiveData 
src/components 폴더에서 Reactive.vue 파일을 열어 아래처럼 수정해줍시다.
 
Reactive.vue
<script>
  //Importing Bar and mixins class from the vue-chartjs wrapper
  import {Bar, mixins} from 'vue-chartjs'
  //Getting the reactiveProp mixin from the mixins module.
  const { reactiveProp } = mixins
  export default {
    extends: Bar,
    mixins: [reactiveProp],
    data () {
      return {
        //Chart.js options that control the appearance of the chart
        options: {
          scales: {
            yAxes: [{
              ticks: {
                beginAtZero: true
              },
              gridLines: {
                display: true
              }
            }],
            xAxes: [ {
              gridLines: {
                display: false
              }
            }]
          },
          legend: {
            display: true
          },
          responsive: true,
          maintainAspectRatio: false
        }
      }
    },
    mounted () {
      // this.chartData is created in the mixin and contains all the data needed to build the chart.
      this.renderChart(this.chartData, this.options)
    }
  }
</script>
 
위 코드에서 한 일은 우선 vue-chartjs wrapper에서 Bar와 mixins를 import하고 Bar를 extend한 것입니다. 다음으로 우리는 reactivity에 사용하기 위해 reactiveProp 믹스인을 mixins 모듈에서 추출했습니다.
 
reactiveProp은 여러분의 차트 컴포넌트의 로직을 확장하고 자동으로 chartData란 이름의 prop을 생성합니다. 그리고 그걸 이 prop의 Vue watcher에 더해줍니다. 이번 코드에서는 필요한 모든 데이터가 chartData prop 내부에 있으므로 dataset 객체를 만들지 않았습니다.
 
이 코드가 동작하기 위해서는 VueChartJS.vue를 먼저 수정해주어야 합니다. VueChartJS.vue를 아래와 같이 수정해주세요.
 
VueChartJS.vue
<template>
    <section class="container">
        <ul>
            <li><router-link to="/">Home</router-link></li>
            <li><router-link to="/chartjs">vue-chartjs</router-link></li>
            <li><router-link to="/charts">vue-charts</router-link></li>
            <li><router-link to="/chartKick">vue-chartKick</router-link></li>
        </ul>
        <h1>Demo examples of vue-chartjs</h1>
        <div class="columns">
            <div class="column">
                <h3>Line Chart</h3>
                <line-chart></line-chart>
            </div>
            <div class="column">
                <h3>Bar Chart</h3>
                <bar-chart></bar-chart>
            </div>
        </div>
        <div class="columns">
            <div class="column">
                <h3>Bubble Chart</h3>
                <bubble-chart></bubble-chart>
            </div>
            <div class="column">
                <h3>Reactivity - Live update upon change in datasets</h3>
                <reactive :chart-data="datacollection"></reactive>
            <button class="button is-primary" @click="fillData()">Randomize</button>
    </div>

</div>
</section >
</template >

    <script>
        import LineChart from '@/components/LineChart'
        import BarChart from '@/components/BarChart'
        import BubbleChart from '@/components/BubbleChart'
        import Reactive from '@/components/Reactive'

        export default {
            name: 'VueChartJS',
        components: {
            LineChart,
            BarChart,
            BubbleChart,
            Reactive
        },
        data() {
return {
            datacollection: null // instantiating datacollection with null
    }
  },
        created() {
            this.fillData() //anytime the vue instance is created, call the fillData() function.
        },
        methods: {
            fillData() {
            this.datacollection = {
                // Data for the y-axis of the chart
                labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
                    'September', 'October', 'November', 'December'
                ],

                datasets: [
                    {
                        label: 'Data One',
                        backgroundColor: '#f87979',
                        // Data for the x-axis of the chart
                        data: [this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(),
                        this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(),
                        this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt()
                        ]
                    }
                ]
            }
        },
        getRandomInt() {
      // JS function to generate numbers to be used for the chart
return Math.floor(Math.random() * (50 - 5 + 1)) + 5
    }
  }
}
    </script>

위 내용을 한번 살펴봅시다. data 객체 안에서 우리는 null로 셋팅된 datacollection을 리턴해줍니다. 그리고 컴포넌트 인스턴스가 생성될 때 created 매소드에서 fillData()를 불러줍니다. fillData 함수는 methods 객체에서 생성됩니다.

method 객체에서 생성한 fillData라는 함수는 label 배열, y축에서 사용될 data 배열을 가진 datasets 배열을 포함한 datacollection 객체를 생성합니다.

 

마지막으로, 우리의 차트를 보여주고 reactivity가 잘 동작하는지 확인하기 위해 <!--Reactivity Line Chart example-->를 

 
<reactive :chart-data="datacollection"></reactive>
<button class="button is-primary" @click="fillData()">Randomize</button>
 
위 코드로 교체해주세요. 
 
이제 우리는 우리가 이전에 생성한 reactive 컴포넌트를 사용하고, 차트를 출력하기 위해 reactiveProp 믹스인이 자동 생성한 chartData 프로퍼티에 datacollection의 컨텐츠를 전달해줍니다. 그리고 데이터를 교체해주기 위한 fillData() 함수를 부르는 버튼을 만들었습니다.
 
/chartjs 라우트로 가서 버튼을 누를 때마다 실시간으로 데이터 값이 바뀌는 새로운 차트를 확인해봅시다.

vue-charts로 차트 만들기 데모

 

마지막 line 차트는 동적으로 데이터를 수정할 수 있습니다. 예를 들어 Label: August, Data: 88 이라는 값을 넣고 Submit하면 

아래와 같이 실시간으로 그래프가 변하는 것을 확인 할 수 있습니다.

 

 

vue-chartkick로 차트 만들기 데모

 

 

위의 두가지 내용에 대해 더 알고 싶으신 분들은 아래 reference의 원문을 참조해주세요.

References

원문 - Creating Beautiful Charts Using Vue.js Wrappers for Chart.js

소스코드 - https://github.com/sitepoint-editors/vue-charts

[Vue.js] chart.js 이용하여 차트 그리기

 

제 글이 도움이 되셨다면 간단하게 '공감', '댓글' 부탁드립니다!

'Languages > Vue.js' 카테고리의 다른 글

Vuex 튜토리얼 코드  (0) 2018.11.22

댓글