129 chart.js 3버전 (이거 많이쓰니깐 잘 알아둬야돼..) (정리중..)

source: categories/study/vue-experiance/vue-experiance_9-99_30.md

129 chart.js 3버전 (이거 많이쓰니깐 잘 알아둬야돼..) (정리중..)



<template>
    <div class="canvas_area">
        <canvas id="myChart" ref="lineChart" width="400" height="400"></canvas>
    </div>
</template>

<script>
    import { mapGetters } from 'vuex';
    import { Chart, registerables } from 'chart.js';
    import moment from '@/plugins/moment';

    Chart.register(...registerables);

    export default {
        name: 'DeviceChartLine',
        props: {
            period: {
                type: Number,
                required: true,
            },
        },
        data() {
            return {
                myChart: null,
                chartData: {
                    type: 'line',
                    data: {
                        labels: [],
                        datasets: [
                            // period 48시간 이내
                            // {
                            //   label: '데이터값',
                            //   backgroundColor: 'rgba(78,118,222,0.3)',
                            //   pointBackgroundColor: '#fff',
                            //   borderWidth: 2,
                            //   borderColor: '#4E76DE',
                            //   pointBorderColor: '#4E76DE',
                            //   data: [40, 85, 90, 20, 60],
                            //   fill: true, // true 일 경우 색상이 채워진다.
                            //   lineTension: 0.4, // 곡선 라인
                            //   pointStyle: ['circle', 'circle', 'crossRot', 'circle', 'circle'],
                            // },
                            {
                                label: '일 평균',
                                backgroundColor: 'rgba(78,118,222,0.3)',
                                pointBackgroundColor: '#fff',
                                borderWidth: 2,
                                borderColor: '#4E76DE',
                                pointBorderColor: '#4E76DE',
                                data: [40, 85, 90, 20, 60],
                                fill: true, // true 일 경우 색상이 채워진다.
                                lineTension: 0.4, // 곡선 라인
                                pointStyle: ['circle', 'circle', 'crossRot', 'circle', 'circle'],
                            },
                            {
                                label: '최소값',
                                backgroundColor: 'transparent',
                                borderWidth: 1,
                                borderDash: [5, 5],
                                borderColor: '#000',
                                pointBorderColor: '#000',
                                data: [10, 10, 10, 10, 10],
                                pointBackgroundColor: '#fff',
                                fill: false,
                                pointRadius: 0,
                                pointHitRadius: 5,
                            },
                            {
                                label: '최대값',
                                backgroundColor: 'rgba(78,118,222,0.3)',
                                pointBackgroundColor: '#fff',
                                borderWidth: 1,
                                borderColor: '#C0502A',
                                pointBorderColor: '#C0502A',
                                data: [10, 10, 10, 10, 10],
                                fill: false,
                                lineTension: 0.4,
                            },
                        ],
                    },
                    options: {
                        grid: {
                            display: true,
                        },
                        interaction: {
                            intersect: false,
                        },
                        scales: {
                            yAxes: {
                                beginAtZero: true,
                            },
                        },
                        plugins: {
                            legend: {
                                display: true,
                            },
                            tooltip: {
                                enabled: true,
                                position: 'nearest',
                                intersect: false,
                                alignment: 'center',
                                custom(tooltip) {
                                    if (!tooltip) {
                                        return;
                                    }
                                    tooltip.displayColors = false;
                                },
                                callbacks: {
                                    title(tooltipItem) {
                                        const { label } = tooltipItem[0];
                                        // const { datasetIndex, label } = tooltipItem[0];
                                        // return datasetIndex === 0 ? label : '평균';
                                        return label;
                                    },
                                },
                            },
                        },
                    },
                },
                // 측정값 또는 일평균
                dataSetType1: {
                    label: '',
                    backgroundColor: 'rgba(78,118,222,0.3)',
                    pointBackgroundColor: '#fff',
                    borderWidth: 2,
                    borderColor: '#4E76DE',
                    pointBorderColor: '#4E76DE',
                    data: [],
                    fill: true, // true 일 경우 색상이 채워진다.
                    lineTension: 0.4, // 곡선 라인
                    pointStyle: ['circle', 'circle', 'crossRot', 'circle', 'circle'],
                },
                // 최소값
                dataSetType2: {
                    label: '',
                    backgroundColor: 'transparent',
                    borderWidth: 1,
                    borderDash: [5, 5],
                    borderColor: '#000',
                    pointBorderColor: '#000',
                    data: [],
                    pointBackgroundColor: '#fff',
                    fill: false,
                    pointRadius: 0,
                    pointHitRadius: 5,
                },
                // 최대값
                dataSetType3: {
                    label: '',
                    backgroundColor: 'rgba(78,118,222,0.3)',
                    pointBackgroundColor: '#fff',
                    borderWidth: 1,
                    borderColor: '#C0502A',
                    pointBorderColor: '#C0502A',
                    data: [],
                    fill: false,
                    lineTension: 0.4,
                },
            };
        },
        computed: {
            ...mapGetters('info', [
                'deviceChartDataList',
                'deviceChartMaxDataList',
                'deviceChartMinDataList',
            ]),
        },
        watch: {
            deviceChartDataList() {
                this.setChartData();
                this.initChart(this.$refs.lineChart, this.chartData);
            },
        },
        beforeDestroy() {
            // 차트 정보 삭제
            if (this.myChart) {
                this.myChart.destroy();
            }
        },
        mounted() {
            this.setChartData();
            this.initChart(this.$refs.lineChart, this.chartData);
        },
        methods: {
            initChart(ref, chartData) {
                const ctx = ref.getContext('2d');
                const gradient = ctx.createLinearGradient(0, 0, 0, 400);

                gradient.addColorStop(0, 'rgba(78,118,222,0.3)');
                gradient.addColorStop(1, 'rgba(78,118,222,0.3)');

                this.chartData.data.datasets[0].backgroundColor = gradient;
                if (this.myChart) {
                    this.myChart.destroy();
                }
                this.myChart = new Chart(ctx, {
                    type: chartData.type,
                    data: chartData.data,
                    options: chartData.options,
                });
            },
            setChartData() {
                const keys = this.deviceChartDataList.map(item => item.name);
                const values = this.deviceChartDataList.map(item => item.value);
                const dataList = values.map(item => (item !== '' ? item : 0));
                const maxValues = this.deviceChartMaxDataList.map(item => item.value);
                const maxDataList = maxValues.map(item => (item !== '' ? item : 0));
                const minValues = this.deviceChartMinDataList.map(item => item.value);
                const minDataList = minValues.map(item => (item !== '' ? item : 0));
                const pointStyle = values.map(item =>
                        item !== '' ? 'circle' : 'crossRot',
                );

                if (this.period < 2) {
                    this.chartData.data.labels = keys.map(item =>
                            moment.getConvertFormat(item, 'MM/DD HH:mm'),
                    );
                    this.$set(this.chartData.data, 'datasets', [
                        {
                            ...this.dataSetType1,
                            label: '측정값',
                            pointStyle,
                            data: dataList,
                        },
                    ]);
                } else {
                    this.chartData.data.labels = keys.map(item =>
                            moment.getConvertFormat(item, 'MM/DD'),
                    );
                    this.$set(this.chartData.data, 'datasets', [
                        {
                            ...this.dataSetType1,
                            label: '일 평균',
                            pointStyle,
                            data: dataList,
                        },
                        {
                            ...this.dataSetType2,
                            label: '최소값',
                            data: minDataList,
                        },
                        {
                            ...this.dataSetType3,
                            label: '최대값',
                            data: maxDataList,
                        },
                    ]);
                }
            },
        },
    };
</script>

<style></style>