Vue-chartjs
Easy and beautiful charts with Chart.js and Vue.js
Vue SPC
<script lang="ts">
import {Component, Prop} from 'vue-property-decorator';
import {mixins} from 'vue-class-component'
import {Bar, mixins as chartJsMixins} from 'vue-chartjs';
const {reactiveProp} = chartJsMixins;
@Component
export default class BarChart extends mixins(Bar, reactiveProp) {
@Prop({type: Object})
readonly options!: object;
mounted () {
this.renderChart(this.chartData, this.options)
}
}
</script>
Chart.js 3.xx 지원을 위한 직접 구현
chart.js@3
부터 vue-chartjs가 빌드 안되더라..
그래서 vue-chart-3를 써봤는데 NODE_ENV=Production
빌드시 에러가 발생되더라..
결국 vue-chartjs를 참조하여 직접 구현했다:
<template>
<div>
<canvas
ref="canvas"
:width="width"
:height="height"
></canvas>
</div>
</template>
<script lang="ts">
import {Vue, Component, Prop, Ref, Watch, Emit} from 'vue-property-decorator';
import type {
ChartType,
ChartData,
ChartOptions,
ChartConfiguration,
Plugin,
} from 'chart.js';
import {Chart as ChartJS} from 'chart.js';
const DEFAULT_TYPE = 'line';
const DEFAULT_WIDTH = 480;
const DEFAULT_HEIGHT = 480;
@Component
export default class Chart extends Vue {
@Prop({type: String, default: DEFAULT_TYPE})
readonly type!: ChartType;
@Prop({type: Number, default: DEFAULT_WIDTH})
readonly width!: number;
@Prop({type: Number, default: DEFAULT_HEIGHT})
readonly height!: number;
@Prop({type: Array, default: () => []})
readonly plugins!: Array<Plugin>;
@Prop({type: Object, default: () => { return {}; } })
readonly chartData!: ChartData;
@Prop({type: Object, default: () => { return {}; } })
readonly options!: ChartOptions;
@Ref()
readonly canvas!: HTMLCanvasElement;
chart?: ChartJS;
beforeDestroy () {
if (this.chart) {
this.chart.destroy();
}
}
renderChart() {
if (this.chart) {
this.chart.destroy();
}
const context = this.canvas.getContext('2d');
if (context === null) {
throw Error('Canvas context is null');
}
const config = {
type: this.type,
data: this.chartData,
options: this.options,
plugins: this.plugins,
} as ChartConfiguration;
this.chart = new ChartJS(context, config);
}
@Watch('chartData')
onChangeChartData(newData, oldData) {
if (oldData && typeof this.chart !== 'undefined') {
let chart = this.chart;
const newDatasetLabels = newData.datasets.map(d => d.label);
const oldDatasetLabels = oldData.datasets.map(d => d.label);
const oldLabels = JSON.stringify(oldDatasetLabels)
const newLabels = JSON.stringify(newDatasetLabels)
// Check if Labels are equal and if dataset length is equal
if (newLabels === oldLabels && oldData.datasets.length === newData.datasets.length) {
newData.datasets.forEach((dataset, i) => {
// Get new and old dataset keys
const oldDatasetKeys = Object.keys(oldData.datasets[i]);
const newDatasetKeys = Object.keys(dataset);
// Get keys that aren't present in the new data
const deletionKeys = oldDatasetKeys.filter((key) => {
return key !== '_meta' && newDatasetKeys.indexOf(key) === -1;
})
// Remove outdated key-value pairs
deletionKeys.forEach((deletionKey) => {
delete chart.data.datasets[i][deletionKey];
})
// Update attributes individually to avoid re-rendering the entire chart
for (const attribute in dataset) {
if (dataset.hasOwnProperty(attribute)) {
chart.data.datasets[i][attribute] = dataset[attribute];
}
}
});
if (newData.hasOwnProperty('labels')) {
chart.data.labels = newData.labels;
this.labelsUpdate();
}
if (newData.hasOwnProperty('xLabels')) {
chart.data['xLabels'] = newData.xLabels;
this.xlabelsUpdate();
}
if (newData.hasOwnProperty('yLabels')) {
chart.data['yLabels'] = newData.yLabels;
this.ylabelsUpdate();
}
chart.update();
this.chartUpdate();
} else {
if (chart) {
chart.destroy();
this.chartDestroy();
}
this.renderChart();
this.chartRender();
}
} else {
if (this.chart) {
this.chart.destroy();
this.chartDestroy();
}
this.renderChart();
this.chartRender();
}
}
@Emit('labels:update')
labelsUpdate() {
}
@Emit('xlabels:update')
xlabelsUpdate() {
}
@Emit('ylabels:update')
ylabelsUpdate() {
}
@Emit('chart:update')
chartUpdate() {
}
@Emit('chart:destroy')
chartDestroy() {
}
@Emit('chart:render')
chartRender() {
}
}
</script>
사용 방법:
See also
- vue
- chart.js
- ApexCharts
- vue-graph
- vue-chart-3 - chart.js 3.x 지원.