使用更新功能后,Chart.js不根据插件重新排序行 [英] Chart.js not resorting rows based on plugin after using update function
问题描述
我正在页面上显示堆积的条形图。初始化表格时,我对数据进行排序,以便在每个数据集中按总数的降序显示。
I'm displaying a stacked bar chart on my page. When I initialize the table, I sort the data so that it is displayed in descending order by total in each dataset.
为此,我使用的是自定义插件
To do this, I'm using a custom plugin
Chart.plugins.register({
datasets: [],
getData(labels, datasets) {
const sum = [];
for (i = 0; i < datasets[0].length; i++) {
sum.push({
label: labels[i],
data: datasets.map(e => e[i]),
get sum() { // ES6 - getter
return this.data.reduce((a, b) => a + b);
}
});
}
return sum;
},
beforeInit(chart) {
chart.data.datasets.forEach((dataset, datasetIndex) => {
this.datasets.push(dataset.data);
});
const data_store = this.getData(chart.data.labels, this.datasets).sort((a,b) => b.sum - a.sum);
data_store.forEach((d,i) => {
chart.data.labels[i] = d.label;
d.data.forEach((v, vi) => {
chart.data.datasets[vi].data[i] = v;
});
});
}
});
p>
Now, every 60 seconds I am running some AJAX to grab updated data to refresh the chart.
setInterval(function() {
$.get("ajax?type=chart_update&id={{ @GET.id }}", function(data){
var data = JSON.parse(data);
data.datasets.forEach(function(value, key) {
chart_data.datasets[key].data = value.data;
});
chart_data.labels = data.labels;
myChart.update();
});
}, 60000);
但是,当我运行更新功能时,数据不再排序。我尝试在插件中使用其他钩子,而不是使用 beforeInit
这样的钩子,例如 beforeUpdate
, beforeRender
和 beforeDraw
,但是这些要么没有作用,使图表呈现异常,要么出现错误
However, when I run the update function, the data is no longer sorted. I've tried to use different hooks in my plugin instead of beforeInit
such as beforeUpdate
, beforeRender
, and beforeDraw
, but these either made no difference, makes the chart render weirdly, or I get the error
未捕获的TypeError:无法读取未定义的属性'data'
Uncaught TypeError: Cannot read property 'data' of undefined
如何我可以在更新后再次对数据进行排序吗?
How can I sort the data again after updating?
推荐答案
排序非常复杂,因为您不能简单地更改数据,还需要知道标签的顺序。您可以在 JSBin 中找到我的代码。我希望这就是您想要的。
The sorting is quite complexe because you can't simply change the data, you need to know the order for the labels as well. You find my code in the JSBin. I hope this is what you want.
完整代码:
let chartOptions = {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
let chartData = {
labels: ["FirstValue", "SecondValue", "ThirdValue", "FourthValue"],
datasets: [{
label: 'FirstDataset',
data: [12, 55, 33, 85],
backgroundColor: 'red'
},{
label: 'SecondDataset',
data: [95, 15, 73, 5],
backgroundColor: 'blue'
},{
label: 'ThirdDataset',
data: [38, 17, 73, 45],
backgroundColor: 'green'
},{
label: 'FourthDataset',
data: [49, 89, 33, 85],
backgroundColor: 'orange'
}]
}
let sortedData = sortData(chartData)
let ctx = document.getElementById("myChart");
let stackedBar = new Chart(ctx, {
type: 'bar',
data: sortedData,
options: chartOptions
});
function sortData(chartData) {
console.log('#############')
console.log('beforeSort', chartData)
let arraySum = []
let sortedData = {}
sortedData.labels = []
sortedData.datasets = []
// Calculate the total sum of all datasets for each label
for (let i = 0; i < chartData.labels.length; i++) {
let dataSum = 0
chartData.datasets.map(obj => {
dataSum += obj.data[i]
})
arraySum.push(dataSum)
}
//console.log("Data sum", arraySum)
// Get a lookup-table with the order of the labels
let arrayLookupTable = []
for (let i = 0; i < chartData.labels.length; i++) {
let index = arraySum.indexOf(Math.max.apply(null,arraySum))
arrayLookupTable.push(index)
arraySum[index] = -1
}
//console.log("arrayLookupTable", arrayLookupTable)
// Assign the sorted labels
for (let i = 0; i < chartData.labels.length; i++) {
sortedData.labels.push(chartData.labels[arrayLookupTable[i]])
}
// Assign the sorted datasets
for (let i = 0; i < chartData.datasets.length; i++) {
sortedData.datasets.push(chartData.datasets[i])
//previous line copies complete dataset with old data which gets sorted in the next line
sortedData.datasets[i].data = changeDataOrder(sortedData.datasets[i].data, arrayLookupTable)
}
console.log("afterSort", sortedData)
return sortedData
}
function changeDataOrder(previousDataArray, arrayLookupTable) {
//console.log('changeDataOrder', previousDataArray, arrayLookupTable)
let newDataArray = []
for (let i = 0; i < arrayLookupTable.length; i++) {
newDataArray.push(previousDataArray[arrayLookupTable[i]])
}
return newDataArray
}
function updateChart() {
chartData.datasets.forEach(function(element) {
element.data = r(chartData.labels.length);
});
let updatedChart = sortData(chartData)
stackedBar.config.data.labels = updatedChart.labels; //labels have to be updated separately
stackedBar.update();
}
function r(length) {
let values = [];
for (i = 0; i < length; i++) {
values.push(Math.floor(Math.random() * 100));
}
return values;
}
这篇关于使用更新功能后,Chart.js不根据插件重新排序行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!