使用更新功能后,Chart.js不根据插件重新排序行 [英] Chart.js not resorting rows based on plugin after using update function

查看:63
本文介绍了使用更新功能后,Chart.js不根据插件重新排序行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在页面上显示堆积的条形图。初始化表格时,我对数据进行排序,以便在每个数据集中按总数的降序显示。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆