본문 바로가기
Programming/Frontend

[VueJs] vue-chartjs 로 멀티라인 그래프 그리기

by BitSense 2020. 5. 11.
반응형

머신러닝 같은 강좌나 책을 읽다 보면 간혹 마주치는 단어가 시계열 혹은 시계열화 이란 것입니다. 말은 어려워 보이는데 영어로는 "time series" 라고 합니다. 한글은 어렵지만 영어는 어느 정도 뜻이 이해가 갑니다. 그냥 순차적으로 먼가 하는 거구나... 라는 센쑤~!

개발자들이 디비 등에서 추출한 정보는 보통 테이블 형식의 텍스트로 제공하는 경우가 많습니다. 이것을 보기 좋게 그래프 형태로 변형해서 보여주면, 직관적으로 이해하게 되고, 실시간 의사결정이 가능해 진다고 합니다. 예전부터 알고는 있었지만, 막상 그래프 표현은 좀 어렵기는 합니다.

vuejs에서는 되게 쉽습니다. 시계열의 대표적인 것이 Line Chart 일 것 같아서, 소스로 좀더 쉽게 만들어 보도록 하겠습니다. Line Charts 는 아래와 같은 형태 입니다.

설치

// 설치
npm i --save vue-chartjs chart.js

LineChart 템플릿 소스 샘플

// 공용 사용 가능성이 있어서 components/Charts 에 컴포넌트 형태로 저장하여 사용
// data = chartData 외부에서 가져옴
// chartData = {labels: ['전체 범주'], data: { label: '그래프 범주', data: []}
<script>
    import {Line} from 'vue-chartjs'

    export default {
        name: 'LineChart',
        extends: Line,
        props: ['chartData'],
        data: () => ({
                colorSets: [ // 여러 그래프 사용을 위해서 색상표 예약
                    {fore: '#EF9A9A', back: '#B71C1C'},
                    {fore: '#F48FB1', back: '#880E4F'},
                    {fore: '#CE93D8', back: '#4A148C'},
                    {fore: '#B39DDB', back: '#311B92'},
                    {fore: '#9FA8DA', back: '#1A237E'},
                    {fore: '#64B5F6', back: '#0D47A1'},
                    {fore: '#4FC3F7', back: '#01579B'},
                    {fore: '#0097A7', back: '#006064'},
                    {fore: '#00897B', back: '#004D40'},
                    {fore: '#81C784', back: '#1B5E20'},
                ],
                datacollection: { // 데이터 샘플
                    // 전체 범주
                    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',
                            // 실제 데이터. labels와 배열 순서가 맞아야 함. 빈곳은 0으로 보정이 필요
                            data: [40, 20, 30, 50, 90, 10, 20, 40, 50, 70, 90, 100]
                        }
                    ]
                },
                options: {
                    scales: {
                        yAxes: [{
                            ticks: {
                                beginAtZero: true
                            },
                            gridLines: {
                                display: true
                            }
                        }],
                        xAxes: [{
                            gridLines: {
                                display: false
                            }
                        }]
                    },
                    legend: {
                        display: true
                    },
                    responsive: true,
                    maintainAspectRatio: false
                }
            }
        ),
        mounted() {
            this.init()
        },
        methods: {
            init() {
                let data = this.chartData.chartData

                let datasets = []
                let pos = 0
                data.forEach((site) => {
                    let colors = this.colorSets[pos]

                    datasets.push({
                        label: site.label,
                        borderWidth: 2,
                        borderColor: colors.back,
                        backgroundColor: colors.back,
                        pointBorderColor: colors.fore,
                        pointBackgroundColor: colors.fore,
                        fill: false,
                        data: site.data
                    })

                    pos++
                })

                this.datacollection = {
                    labels: this.chartData.labels,
                    datasets: datasets
                }

                this.render()
            },
            render() {
                this.renderChart(this.datacollection, this.options)
            }

        }
    }
</script>

<style scoped>

</style>

vuejs 샘플 소스

<template>
    <v-container fluid>
        <v-row>
          <v-col>
            <div class="text-lg-center pa-5" style="width: 100%;" v-if="chartLoading">
              <v-progress-circular
                  width="7"
                  size="70"
                  indeterminate
                  color="red"
              ></v-progress-circular>
            </div>
            <line-chart :chartData="chartData" v-if="!chartLoading"/>
          </v-col>
        </v-row>
    </v-container>
</template>

<script>
    // '@/components/Charts/LineChart' 사용 가능하면 대체를 해도 된다.
    import LineChart from '../Charts/LineChart'

    export default {
        name: 'List',
        components: { LineChart },
        data: () => ({
            chartLoading: false, // 데이터를 불러오기 전까지는 progress circle을 사용
            chartData: []
        }),
        mounted() {
            this.init()
        },
        methods: {
            init() {
                let item = '{"labels":["01","02","03","04","05","06","07","08","09","10","11"],"chartData":[{"label":"다음","data":["65","13","22","125","41","142","156","121","24","29","151"]},{"label":"다우존스","data":["1","1","0","6","1","3","6","8","0","0","6"]},{"label":"네이버","data":["65","13","22","119","41","139","150","119","20","28","147"]},{"label":"뉴스원","data":["61","7","17","105","28","128","138","108","10","20","137"]},{"label":"다나와","data":["0","0","0","1","0","0","1","0","0","0","0"]}]}'
            	let data = JSON.parse(item)
                
                this.chartData = {
                    labels: data.labels,
                    chartData: data.chartData
                }

                // 차트 보이기
                this.chartLoading = false
            }
    }
</script>

<style scoped>
 
</style>

 

소스 샘플 결과

반응형