3
votes

Can anyone show me the mathematical logic that Chart.js 2.6+ uses to calculate the Y-axis in a bar chart? I have created a pagination feature to allow me to page through a bar chart that has a massive amount of columns. It works great except that I need the Y-axis to remain constant as the data set for the chart changes.

For this, I take the data for the chart and create a subset of it, for example the first 20 records, and supply this to the chart as the data object. To make the Y-axis fixed though, I take the largest value in the full dataset and supply that as the max value in the ticks for the yAxes object in the chart as seen below.

yAxes: [{
     ticks: {
          max:value_i_determine_here
     }
}]

This does work but not perfectly because Chart.js will sometimes create the steps too closely together resulting in a chart that looks like the one below.

enter image description here

As you can see, the top value is 1,900,000 because I am supplying that as the max value. However I need to supply the max value as the value I determine with respect to the steps Chart.js has determined should be used.

So my question is, how does Chart.js calculate what values to use in the Y-axis? If I know this logic, then I use that logic to get the max value based on my full data set and supply THAT value as the max.

2
It looks like it takes an step of 200K but it still represents the maximum yAxis value. I guess it results even worse if the maximum value is 180,001.lilezek

2 Answers

0
votes

What I ended up doing is writing a function that will take the max value in my full dataset and divide it by the value I supply to the Y Axis maxTicksLimit attribute. Then I run this value through complex if/else if condition that looks something like the following.

Then I use what is returned as step and supply that to the chart as the Y axis stepSize attribute. Looks to work pretty good. If anyone has a better solution PLEASE let me know as this one is based on my hard coded calculations and I would prefer a more dynamic approach.

var determineStepSize = function(maxDatasetValue) {
     var maxStepTemp = Math.ceil(maxDatasetValue / maxYAxisTicks);
     // Determine what the step should be based on the maxStepTemp value
     if (maxStepTemp > 4000000) step = 8000000;
     else if (maxStepTemp > 2000000) step = 4000000;
     else if (maxStepTemp > 1000000) step = 2000000;
     else if (maxStepTemp > 500000) step = 1000000;
     else if (maxStepTemp > 250000) step = 500000;
     else if (maxStepTemp > 100000) step = 200000;          
     else if (maxStepTemp > 50000) step = 100000;
     else if (maxStepTemp > 25000) step = 50000;
     else if (maxStepTemp > 10000) step = 20000;
     else if (maxStepTemp > 5000) step = 10000;
     else if (maxStepTemp > 2500) step = 5000;
     else if (maxStepTemp > 1000) step = 2000;
     else if (maxStepTemp > 500) step = 1000;
     else step = 500;                   
     return step;
};
0
votes

I found in the similar situation as you. I created a more generic approach by using a stepSize and max attributes.

// StepSize Function
stepSize = (maxValue) => {
  return parseInt((this.maxValue / (numberOfRowsYouWant - 1)).toFixed(0));
} 

// In Scale Options
scales: {
  yAxes: [{
    display: true,
    ticks: {
       max: this.maxValue + this.stepSize(),
       stepSize: this.stepSize(),
       display: true,
       beginAtZero: true
    }
  }]
}