问题描述
我正在一个项目中,我正在实现Vue-Chartjs库中的一些图表。每当用户更改给定的过滤器时,我都需要更改Y轴最大值。我从vue-chartjs库导入现有的条形图。在代码中,有一个javascript文件已经具有一些默认值,以设置额外的选项,我可以使用extraOptions对象作为道具来相应地个性化每个图表。这是默认组件:
import { Bar } from 'vue-chartjs'
import { hexToRGB } from "./utils";
import reactiveChartMixin from "./mixins/reactiveChart";
let defaultOptions = {
tooltips: {
tooltipFillColor: "rgba(0,0.5)",tooltipFontFamily: "'Helvetica Neue','Helvetica','Arial',sans-serif",tooltipFontSize: 14,tooltipFontStyle: "normal",tooltipFontColor: "#fff",tooltipTitleFontFamily: "'Helvetica Neue',tooltipTitleFontSize: 14,tooltipTitleFontStyle: "bold",tooltipTitleFontColor: "#fff",tooltipYPadding: 6,tooltipXPadding: 6,tooltipCaretSize: 8,tooltipCornerRadius: 6,tooltipXOffset: 10,},legend: {
display: false
},scales: {
yAxes: [{
ticks: {
fontColor: "#9f9f9f",fontStyle: "bold",beginAtZero: true,display: false,min: 0,max: 100
},gridLines: {
display: false,drawBorder: false,}
}],xAxes: [{
gridLines: {
display: false,}],}
};
export default {
name: 'BarChart',extends: Bar,mixins: [reactiveChartMixin],props: {
labels: {
type: [Object,Array],description: 'Chart labels. This is overridden when `data` is provided'
},datasets: {
type: [Object,description: 'Chart datasets. This is overridden when `data` is provided'
},data: {
type: [Object,description: 'Chart.js chart data (overrides all default data)'
},color: {
type: String,description: 'Chart color. This is overridden when `data` is provided'
},extraOptions: {
type: Object,description: 'Chart.js options'
},title: {
type: String,description: 'Chart title'
},methods: {
assignChartData() {
let { gradientFill } = this.assignChartOptions(defaultOptions);
let color = this.color || this.fallBackColor;
return {
labels: this.labels || [],datasets: this.datasets ? this.datasets : [{
label: this.title || '',backgroundColor: gradientFill,borderColor: color,pointBorderColor: "#FFF",pointBackgroundColor: color,pointBorderWidth: 2,pointHoverRadius: 4,pointHoverBorderWidth: 1,poinTradius: 4,fill: true,borderWidth: 1,data: this.data || []
}]
}
},assignChartOptions(initialConfig) {
let color = this.color || this.fallBackColor;
const ctx = document.getElementById(this.chartId).getContext('2d');
const gradientFill = ctx.createLinearGradient(0,170,50);
gradientFill.addColorStop(0,"rgba(128,182,244,0)");
gradientFill.addColorStop(1,hexToRGB(color,0.6));
let extraOptions = this.extraOptions || {}
return {
...initialConfig,...extraOptions,gradientFill
};
}
},mounted() {
this.chartData = this.assignChartData({});
this.options = this.assignChartOptions(defaultOptions);
this.renderChart(this.chartData,this.options,this.extraOptions);
}
}
我使用此js文件将条形图导入vue组件内部,如您在下面看到的那样。
每次表单输入更改时,我都需要重新呈现图表。我使用onInputChange()
方法将布尔值loaded
设置为false并调用loadData()
方法。
在loadData()
方法内部,我发出了一个axios请求,每次都获取正确的数据。我也获得了Y轴的最大值。
然后在响应中调用updateChart()
,以便可以更新数据和图表的最大值。然后我将布尔值loaded
再次设为true,以使我的图表相应地呈现。
此方法的问题在于,图表会在一秒钟内完全消失。在决定更改Y轴的最大值之前,我无需使用v-if =“ loaded”就可以更新图表的数据。
我需要找到一种解决方案,在该解决方案中重新呈现图表,而图表不会完全从页面中消失。我知道有人建议使用计算变量,但我不完全了解它应该如何工作。这是减去表单字段的组件。
我想本质上来说我想要的是更新Y轴最大值而不必重新呈现整个图表。
<template>
<div>
<BarChart v-if="loaded" :labels="chartLabels"
:datasets="datasets"
:height="100"
:extraOptions="extraOptions"
>
</BarChart>
<br>
</div>
</template>
<script>
import BarChart from '../../components/Library/uicomponents/Charts/BarChart'
import Dropdown from "../../components/Library/uicomponents/Dropdown"
import GroupedMultiSelectWidget from "~/components/widgets/GroupedMultiSelectWidget"
import SelectWidget from "../../components/widgets/SelectWidget";
export default{
name: 'PopularChart',components: {BarChart,Dropdown,SelectWidget,GroupedMultiSelectWidget},data(){
return {
loaded:true,form:{
day: 'Today',workspace:'',machine_family: [],duration: [],user_group: [],dt_start:'',dt_end:''
},url: `/api/data_app/job_count_by_hour/`,chart_data: [],days: [ {day:"Today",id:"Today"},{day:"Monday",id:"0"},{day:"Tuesday",id:"1"},{day:"Wednesday",id:"2"},{day:"Thursday",id:"3"},{day:"Friday",id:"4"},{day:"Saturday",id:"5"},{day:"sunday",id:"6"} ],chartLabels: ["00u","1u","2u","3u","4u","5u","6u","7u","8u","9u","10u","11u","12u","13u","14u","15u","16u","17","18u","19u","20u","21u","22u","23u"],datasets: [],maximumValue: '',extraOptions:{}
}
},methods: {
onInputChange() {
this.loaded = false
this.loadData()
},async loadData() {
await this.$axios.get(`${this.url}?day=${this.form.day}&date_start=${this.form.dt_start}&date_end=${this.form.dt_end}&workspace=${this.form.workspace}&user_group=${this.form.user_group}&machine_family=${this.form.machine_family}`)
.then(response => {
this.updateChart(response.data.results,response.data.maximum)
this.loaded = true
})
},updateChart(data,maxValue) {
this.datasets = [{
label: ["jobs %"],backgroundColor:"#f93232",data: data
},]
this.maximumValue = maxValue
this.extraOptions = {
tooltips: {
callbacks:{
label: function (tooltipItems,){
if (tooltipItems.value > ((50/100) * maxValue)){
return 'busy';
}else if (tooltipItems.value < ((30/ 100) * maxValue) ){
return ' not busy';
}else if ( tooltipItems.value < ((40/ 100) * maxValue )){
return 'kind of busy'
}
}
}
},scales: {
yAxes: [{
gridLines: {
zeroLineColor: "transparent",ticks: {
max: this.maximumValue,display: true,}
}],xAxes: [{
gridLines: {
zeroLineColor: "transparent",}
},mounted() {
this.loadData()
},}
</script>
解决方法
您可以将图表绑定到data()
中的变量,并使用mounted()
中的某些默认值对其进行初始化,并且每当要更新图表数据时,都可以使用Chart.js API。
一个实现可能看起来像这样:
export default {
data() {
return {
chart: null
};
},mounted() {
this.chart = new Chart(/* defaults */);
},methods: {
updateChart(data) {
this.chart.data.datasets = data;
/* rest of the chart updating */
this.chart.update();
}
}
};