Chartjs 条形图在悬停时显示旧数据
我有一个使用 chart.js 创建的条形图.页面加载时一切正常,但是当我使用 daterangepicker 更改时间范围时,会出现故障.新数据被引入,但是当我将鼠标悬停在它上面时,会显示旧数据.我是 javascript 新手,所以我希望能得到一些帮助.看起来我需要合并 .destroy();不知何故,但我不知道如何.我的代码片段如下:
I have a bar chart that's created using chart.js. Everything works fine on page load, but when I change the time frame using a daterangepicker, a glitch appears. The new data is brought in, but when I hover over it, the old data is shown. I'm new to javascript so I'm hoping to get some help. It looks like I need to incorporate .destroy(); somehow, but I don't know how. A snippet of my code is below:
function loadFTPRChart(startdate, enddate){
var BCData = {
labels: [],
datasets: [
{
label: "Pass %",
backgroundColor: "#536A7F",
data: [],
stack: 1
},
{
label: "Fail %",
backgroundColor: "#e6e6e6",
data: [],
stack: 1
},
{
label: "Auto %",
backgroundColor: "#286090",
data: [],
stack: 2
},
{
label: "Manual %",
backgroundColor: "#f0f0f0",
data: [],
stack: 2
}
]
};
$.getJSON( "content/FTPR_AM_Graph_ajax.php", {
startdate: startdate,
enddate: enddate,
location: "M"
})
.done(function( data ) {
console.log("data", data);
$.each( data.aaData, function( key, val ) {
if(val == ""){return true}
BCData.labels.push("Coater " + val[0]);
BCData.datasets[0].data.push(parseFloat(val[2]));
BCData.datasets[1].data.push(parseFloat(100-val[2]));
BCData.datasets[2].data.push(parseFloat(val[1]));
BCData.datasets[3].data.push(parseFloat(100-val[1]));
});
var option = {
responsive:true,
};
console.log("BCData", BCData);
//console.log("PrevData", data);
var ctx = document.getElementById("mybarChart2").getContext("2d");
new Chart(ctx, {
type: 'groupableBar',
data: BCData,
options: {
scales: {
yAxes: [{
ticks: {
max: 100,
},
stacked: true,
}]
}
}
});
});
}
loadFTPRChart($('#reportrange').data().daterangepicker.startDate.format('MM/DD/YYYY'), $('#reportrange').data().daterangepicker.endDate.format('MM/DD/YYYY'));
销毁原始数据的最佳方法是什么,以便当我更改日期范围并将鼠标悬停在新图表上时,旧数据不再闪烁?
What is the best way to destroy the original data so that when I change the date range and hover over the new chart, the old data no longer flickers?
谢谢
推荐答案
使用您所采取的方法(例如,每次日期范围更改时创建一个新的 Chart 对象),那么您必须先销毁以前的图表,然后再创建新的.
With the approach you are taking (e.g. creating a new Chart object each time the date range changes), then you must first destroy the previous chart and then create the new one.
您可以使用 .destroy()
原型方法来做到这一点.这正是 API 声明的内容.
You can use the .destroy()
prototype method to do this. Here is exactly what the API states.
使用它来销毁任何已创建的图表实例.这会清理存储在 Chart.js 中的图表对象的所有引用,以及 Chart.js 附加的任何关联事件侦听器.这必须在画布重新用于新图表之前调用.
Use this to destroy any chart instances that are created. This will clean up any references stored to the chart object within Chart.js, along with any associated event listeners attached by Chart.js. This must be called before the canvas is reused for a new chart.
因此,您的代码将如下所示(注意我们会销毁并重新创建).
Therefore, your code would look something like this (notice that we destroy and re-create).
// define a variable to store the chart instance (this must be outside of your function)
var myChart;
function loadFTPRChart(startdate, enddate) {
var BCData = {
labels: [],
datasets: [{
label: "Pass %",
backgroundColor: "#536A7F",
data: [],
stack: 1
}, {
label: "Fail %",
backgroundColor: "#e6e6e6",
data: [],
stack: 1
}, {
label: "Auto %",
backgroundColor: "#286090",
data: [],
stack: 2
}, {
label: "Manual %",
backgroundColor: "#f0f0f0",
data: [],
stack: 2
}]
};
$.getJSON("content/FTPR_AM_Graph_ajax.php", {
startdate: startdate,
enddate: enddate,
location: "M"
})
.done(function(data) {
console.log("data", data);
$.each(data.aaData, function(key, val) {
if (val == "") {
return true
}
BCData.labels.push("Coater " + val[0]);
BCData.datasets[0].data.push(parseFloat(val[2]));
BCData.datasets[1].data.push(parseFloat(100 - val[2]));
BCData.datasets[2].data.push(parseFloat(val[1]));
BCData.datasets[3].data.push(parseFloat(100 - val[1]));
});
var option = {
responsive: true,
};
console.log("BCData", BCData);
// if the chart is not undefined (e.g. it has been created)
// then destory the old one so we can create a new one later
if (myChart) {
myChart.destroy();
}
var ctx = document.getElementById("mybarChart2").getContext("2d");
myChart = new Chart(ctx, {
type: 'groupableBar',
data: BCData,
options: {
scales: {
yAxes: [{
ticks: {
max: 100,
},
stacked: true,
}]
}
}
});
});
}
话虽如此,一遍又一遍地销毁/创建是昂贵的,实际上它甚至没有必要.还有另一种原型方法称为 .update()
,如果您更改了图表的基础数据或标签对象,您可以使用该方法重新渲染图表.
With that said, it's expensive the destroy/create over and over and actually it isn't even necessary. There is another prototype method called .update()
that you can use to just re-render the chart if you have changed it's underlying data or label objects.
这里有一个 jsfiddle 展示了一个改变底层数据和标签然后重新渲染的例子图表.我强烈建议您改用这种方法.
Here is a jsfiddle showing an example of changing the underlying data and labels and then re-rendering the chart. I would highly recommend you take this approach instead.
这是您的代码采用这种更好的方法后的样子.
Here is how your code would look taking this better approach.
// define a variable to store the chart instance (this must be outside of your function)
var myChart;
function loadFTPRChart(startdate, enddate) {
var BCData = {
labels: [],
datasets: [{
label: "Pass %",
backgroundColor: "#536A7F",
data: [],
stack: 1
}, {
label: "Fail %",
backgroundColor: "#e6e6e6",
data: [],
stack: 1
}, {
label: "Auto %",
backgroundColor: "#286090",
data: [],
stack: 2
}, {
label: "Manual %",
backgroundColor: "#f0f0f0",
data: [],
stack: 2
}]
};
$.getJSON("content/FTPR_AM_Graph_ajax.php", {
startdate: startdate,
enddate: enddate,
location: "M"
})
.done(function(data) {
console.log("data", data);
$.each(data.aaData, function(key, val) {
if (val == "") {
return true
}
BCData.labels.push("Coater " + val[0]);
BCData.datasets[0].data.push(parseFloat(val[2]));
BCData.datasets[1].data.push(parseFloat(100 - val[2]));
BCData.datasets[2].data.push(parseFloat(val[1]));
BCData.datasets[3].data.push(parseFloat(100 - val[1]));
});
var option = {
responsive: true,
};
console.log("BCData", BCData);
// if the chart is not undefined (e.g. it has been created)
// then just update the underlying labels and data for each
// dataset and re-render the chart
if (myChart) {
myChart.data.labels = BCData.labels;
myChart.data.datasets[0].data = BCData.datasets[0].data;
myChart.data.datasets[1].data = BCData.datasets[1].data;
myChart.data.datasets[2].data = BCData.datasets[2].data;
myChart.data.datasets[3].data = BCData.datasets[3].data;
myChart.update();
} else {
// otherwise, this is the first time we are loading so create the chart
var ctx = document.getElementById("mybarChart2").getContext("2d");
myChart = new Chart(ctx, {
type: 'groupableBar',
data: BCData,
options: {
scales: {
yAxes: [{
ticks: {
max: 100,
},
stacked: true,
}]
}
}
});
}
});
}
相关文章