健康)状况
我在没有包装器的情况下在 Vue 3 中使用 Chartjs,并且能够成功呈现我的图表。图表数据存储在 Vuex 存储中,我每 5 秒更新一次 Vuex 存储状态(轮询 Restful API)。我发现,根据新数据更新图表的唯一安全方法是每次都destroy()
重新调整图表。renderChart()
这似乎有点矫枉过正,因为 Chartjs 具有update()
可用的功能。
如果我尝试用命令替换destroy()
andrenderChart()
命令update(0)
,我的 CPU 很快就会溢出(达到 150% +)。因为我不希望图表每 5 秒重新设置一次动画,所以我的解决方案是在变量中设置动画时间,this.animation
初始渲染设置为 2000,然后为所有后续渲染设置为 0。
这会在第一次加载页面时为图表提供动画,随后的重绘对查看器“隐藏”(无动画)。
期望的结果
更新 Vuex 存储状态时更新图表(而不是销毁和重新渲染)。
图表组件
这个文件中的重要部分(我认为)是mounted()
和watch.data
<template>
<canvas width="100%" height="100%" :id="id"/>
</template>
<script>
import Chart from "chart.js/auto";
import annotationPlugin from 'chartjs-plugin-annotation';
import ChartDataLabels from 'chartjs-plugin-datalabels';
Chart.register(annotationPlugin);
Chart.register(ChartDataLabels);
export default {
name: "ChartPressure8day.vue",
props: ['id', 'data'],
data() {
return {
pressureChart: null,
animation: 2000,
pressureLabels: [
this.data['d01_day_short'], this.data['d02_day_short'], this.data['d03_day_short'], this.data['d04_day_short'],
this.data['d05_day_short'], this.data['d06_day_short'], this.data['d07_day_short'], this.data['d08_day_short'],
],
pressureData: [
this.data['d01_pressure'], this.data['d02_pressure'], this.data['d03_pressure'], this.data['d04_pressure'],
this.data['d05_pressure'], this.data['d06_pressure'], this.data['d07_pressure'], this.data['d08_pressure'],
],
chartMaxY: Math.max(...[
this.data['d01_pressure'], this.data['d02_pressure'], this.data['d03_pressure'], this.data['d04_pressure'],
this.data['d05_pressure'], this.data['d06_pressure'], this.data['d07_pressure'], this.data['d08_pressure'],
]),
}
},
mounted() {
this.renderChart()
},
watch: {
// the intention here is to rerender the chart when the data changes.
data: function (){
// this.pressureChart.update(0)
this.pressureChart.destroy()
this.animation = 0
this.renderChart()
}
},
methods: {
renderChart() {
let ctx = document.getElementById(this.id).getContext('2d');
this.pressureChart = new Chart(ctx, {
options: {
layout: {
padding: {
right: 20,
}
},
plugins: {
datalabels: {
backgroundColor: function (context) {
return context.dataset.backgroundColor;
},
borderRadius: 4,
color: '#888888',
font: {
weight: 'bold'
},
},
annotation: {
annotations: {
line1: {
type: 'line',
label: {
color: '#888888',
enabled: true,
content: 'normal',
font: {
style: 'normal',
size: 9,
position: 'start',
},
},
yMin: 1015,
yMax: 1015,
borderColor: 'rgb(255, 255, 0, 0.4)',
borderWidth: 1,
borderDash: [5, 5],
adjustScaleRange: false,
},
}
},
tooltip: {
position: 'nearest',
},
legend: {
display: false,
},
},
responsive: true,
scales: {
x: {
categoryPercentage: 0.5,
stacked: false,
fontSize: 5,
grid: {
color: "#333333",
display: true,
borderDash: [1, 2],
},
},
y: {
grid:{
color: "#333333",
display: true,
borderDash: [1, 2],
},
ticks: {
stepSize: 10,
},
barPercentage: 0,
categoryPercentage: 0,
fontSize: 5,
// min: 970,
max: Math.ceil((this.chartMaxY + 10) / 10) * 10,
stacked: false,
position: 'left',
},
},
maintainAspectRatio: false,
animation: {
duration: this.animation,
easing:'easeInOutQuart'
}
},
data: {
labels: this.pressureLabels,
datasets: [
{type: 'line',
backgroundColor: "rgba(200, 200, 0, 0.2)",
borderColor: "rgba(200, 200, 0, 1)",
borderRadius: 3,
data: this.pressureData,
hoverBackgroundColor: "rgba(200, 200, 0, 0.5)",
label: "",
yAxisID: 'y',
datalabels: {
align: 'end',
}
},
]
},
},
Chart.defaults.elements.point.radius = 0,
Chart.defaults.elements.point.hoverRadius = 0,
Chart.defaults.elements.point.pointStyle = 'triangle',
Chart.defaults.elements.bar.borderWidth = 1,
Chart.defaults.elements.line.borderWidth = 1,
);
}
},
}
</script>
编辑 1:我刚刚发现这种方法的一个副作用(销毁和重新渲染)是,如果光标悬停在图表上 - 就像显示工具提示时一样 - 它最终会导致错误canvas.getContext
,大概是因为图表对象在光标下被破坏。我认为这可以通过update()
.
编辑 2:为清晰和布局对图表代码进行了细微改进(无功能更改)。