03.업/15.Vue.js

lineChart 작업

봄날의차 2023. 10. 25. 13:31

chart.js 3.0.0버전으로 설치 후 vue2.6으로 작업

데이터쿼리 조회는 springboot로 작업 

파일1 D:***\bidCalCre.vue
파일2 D:***\bidCalLineChart.vue

>>파일1
1.vue <template></template>

    <!-- 그래프 -->
    <div class="flex flex-col mx-auto" style="width: 1168px;">
      <div class="flex mt-2 mb-5">
        <p>*변동율 추이 line</p>
      </div>
      <table>
          <tr>
            <td> 
              <chart :list_dat_avg="list_dat_avg_line" /> 
              <!-- 
              bidCalLineChart.vue 참조파일에서 호출할 데이터 값 지정
              list_dat_avg 호출할 속성변수명
              -->
            </td>
          </tr>
      </table>
    </div> 
  <!--  그래프 끝 -->
  
2.script
<script lang="ts">  
import Vue from 'vue'
// 1.참조페이지 호출 
import chart from '~/bidCalLineChart.vue' 

..
// 2.컴포넌트 호출 
  components: {
   chart
  },

// 3.data로 지정:전역변수지정 LIST_DAT_AVG 계산시 활용할 변수로 지정해서 사용함...list_dat_avg_line를 이용해서 지정없이 해도 될까..?
    data(){
    ...
        , LIST_DAT_AVG: [] as any
        , list_dat_avg_line: [] as any
    ...
    }  

// 4.페이지로드시에 실행선그래프를 위한 계산을 호출 해서 선그래프를 그린다.
    mounted () {
    ...
        this.getDatAvgList(); // 선그래프를 위한 계산     
    ...
    }
    
// 5.선그래프를 위한 계산  : springboot 호출
    async getDatAvgList(){ // 
      this.LIST_DAT_AVG = [] ; // 초기화 
      const res_list_dat_avg = await this.$axios.post('/***/getDatAvgList', this.BasBidInf );      
      
      this.LIST_DAT_AVG = res_list_dat_avg.data;  
            
      this.initializeLineData() ; // 선그래프호출
    },

// 6.선그래프 작성
     initializeLineData() { //getDatAvgList
     // 데이터를 1부터 12까지 생성하여 rows 배열에 할당    
      this.list_dat_avg_line = []; 
      let len = this.LIST_DAT_AVG.length;

      if(this.LIST_DAT_AVG && Array.isArray(this.LIST_DAT_AVG) && this.LIST_DAT_AVG.length > 0 ){
        
        //데이터맵핑
        for(let i=1;i<=len; i++){
          if(i<=this.LIST_DAT_AVG.length){
            this.list_dat_avg_line.push({
              id: i,
              ym: this.LIST_DAT_AVG[i-1].YM,
              avg_con_amo: this.LIST_DAT_AVG[i-1].AVG_CON_AMO
            })
          } else {
            this.list_dat_avg_line.push({
              id: 1,
              ym: '',
              avg_con_amo: 0
            });
          }
        }
      } else {
        for (let i = 1; i <= len; i++) {
          this.list_dat_avg_line.push({
            id: 1,
            ym: '',
            avg_con_amo: 0
          });
        }
      }

    },
    
>>파일2   
// 1.canvas 설정 id 
<template>
    <div class="line_chart">
      <canvas id="lineChart" width="60" height="60"></canvas>
    </div>
</template>

// 2.chart.js 참조
  <script lang="ts">
  import Vue from "vue";
  import { Chart, registerables } from "chart.js";
  
  Chart.register(...registerables);

// 3.list_dat_avg lineChart 데이터 속성 추가  
// data에lineChart 프로퍼티 전역변수 추가: rowList, lineChart
// watch에list_dat_avg이 변경될 때 실행되는 로직과 새로운 데이터로 차트 업데이트 등의 로직 추가
// mounted에데이터 맵핑과 새로운 데이터로 차트 업데이트로직추가:  this.rowList = this.list_dat_avg; 데이터 맵핑 this.updateChart(); 새로운 데이터로 차트 업데이트
// beforeDestroy : 챠트새로그리기 위해 destroy시킨다.
// renderChart updateChart 구현
  export default Vue.extend({
    //name: 'LineChart',
    props: {
      list_dat_avg: { // lineChart 데이터 속성 추가
        type: Array,
        required: true,
      },
    },
    data() {
      return {
        rowList: [] as any,
        lineChart: null as Chart | null, // lineChart 프로퍼티 전역변수 추가
      };
    },
    watch: {
      list_dat_avg: {
        handler(newRows) {
          // list_dat_avg이 변경될 때 실행되는 로직
          this.rowList = newRows;
  
          // 새로운 데이터로 차트 업데이트 등의 로직을 수행할 수 있습니다.
          this.updateChart();
        },
        deep: true,
        immediate: true, // 컴포넌트가 마운트될 때도 실행
      },
    },
    mounted() {    
      this.rowList = this.list_dat_avg;
      this.updateChart();
    },
    beforeDestroy(){
      if (this.lineChart) {
        this.lineChart.destroy();
      }
    },
    methods: {
      renderChart() {
        const canvas = document.getElementById('lineChart') as HTMLCanvasElement;
        if (!canvas) {
          console.error("Canvas element not found");
          return;
        }
  
        const ctx = canvas.getContext('2d');
        if (!ctx) return;
  
        // 데이터맵핑
        const labels = this.rowList.map((d) => d.ym);
        const data = this.rowList.map((d) => d.avg_con_amo);
  
        this.lineChart = new Chart(ctx, {
          type: 'line',
          data: {
            labels,
            datasets: [{
              label: 'Average Data',
              data,
              fill: false,
              borderColor: 'rgb(75, 192, 192)',
            }],
          },
          options: {
            maintainAspectRatio: false,
            scales: {
              y: {
                beginAtZero: true,
              },
            },
          },
        });
      },
    // 기존 차트 인스턴스를 파괴한 후 Vue의 nextTick 함수를 사용하여 DOM 업데이트 사이클이 완료될 때까지 기다립니다
    async updateChart() {
      if (this.lineChart) {
          this.lineChart.data.labels = this.rowList.map((d) => d.ym);
          this.lineChart.data.datasets[0].data = this.rowList.map((d) => d.avg_con_amo);
          this.lineChart.update();
      } else {
        this.renderChart();
      }
    },
  },
  
  });
  </script>
  
  <style scoped>
    .line_chart {
      width: 1160px;
      height: 400px;
    }
  </style>