Chart.js - Setting max Y axis value and keeping steps correct
Asked Answered
M

2

6

I'm using Chart.js 2.6. I have a chart to which I've added custom pagination to step through the dataset, as it is quite large. My pagination and everything works great, I simply grab the next chunk of data in my set and update the chart.config.data with the new data object, and then call .update() on the chart. However, in order to make the chart make sense, I needed to keep the left (Y-axis) scale the same when the user is paginating through. Normally Chart.js would rebuild it based on the data in the chart, but I want it to always reflect the same values.

I've set the max value on the yAxes object of the chart to the maximum value in my data set. I've also set the beginAtZero option to true, and the maxTicksLimit to 10. However, even though my Yaxis does stay the same, it doesn't always look that great (see below screenshot). In this example, my max is set to 21,000 in the chart. Does anyone have any suggestions as to how I can either provide a better max (rounding up to next 5,000, 500, 100, etc based on the value) or some way to get it to create the Y axis without crunching the top number the way it does now?

enter image description here

Here is the function I currently use to determining the max data value to set as the max value in the Yaxes object in the chart. the plugin.settings.chartData variable represents an array of the data values used in the chart. I am trying to get it to increment correctly to the next 1000, 500, etc based on what the maxValue is, but as you can see my math is not correct. In the screenshot example, the maxValue is coming back as 20,750 and my function is rounding it up to 21,000. In this example it SHOULD round it up to the next increment which would be 25,000.

var determineMaxDataValue = function() {
    var maxValue = Math.max.apply(Math, plugin.settings.chartData);
    var step = maxValue > 1000 ? 1000 : 500;
    plugin.settings.maxDataValue = (Math.ceil(maxValue / step) * step);             
};
Makkah answered 3/7, 2017 at 14:8 Comment(0)
M
6

Figured it out. Instead of supplying the max value on the Y Axis as I have been, I instead implemented the afterBuildTicks callback and updated the ticks to have the correct increments.

yAxes: [{
  afterBuildTicks: function(scale) {
  scale.ticks = updateChartTicks(scale);
    return;
  },
  beforeUpdate: function(oScale) {
    return;
  },
  ticks: {  
    beginAtZero:true,
    // max:plugin.settings.maxDataValue,
    maxTicksLimit: 10
  }
}] 

my updateChartTicks function loops over the existing ticks and determines the correct increment amount between the ticks. Then I use that value to add my final "tick" which will always be greater than the largest data in the dataset.

var updateChartTicks = function(scale) {
  var incrementAmount = 0;
  var previousAmount = 0;
  var newTicks = [];
  newTicks = scale.ticks;
  for (x=0;x<newTicks.length;x++) {
    incrementAmount = (previousAmount - newTicks[x]);
    previousAmount = newTicks[x];   
  }
  if (newTicks.length > 2) {
    if (newTicks[0] - newTicks[1] != incrementAmount) {
      newTicks[0] = newTicks[1] + incrementAmount;                  
    }
  }         
  return newTicks;          
};
Makkah answered 3/7, 2017 at 16:9 Comment(0)
T
16

I too had the same problem. You needn't write any special function for determining the max value in the Yaxes. Use 'suggestedMax' setting. Instead for setting 'max' as maximum value in your graph, set suggestMax as the maximum value in your graph. This never works if you have set 'stepsize'.

options: {
 scales: {
  yAxes: [{
    ticks: {
     suggestedMax: maxvalue+20
     }
   }]
  }
}

20 is added, so that the tooltip on max value will be clearly visible.

For more info, refer http://www.chartjs.org/docs/latest/axes/cartesian/linear.html#axis-range-settings

Tacita answered 30/10, 2017 at 5:24 Comment(3)
From where do you get maxvalue ?Mystical
@Aarvy maxvalue is the greatest value in your dataset.Tacita
I get an error when I just use maxvalue. Just for reference I'm using the library with ReactJS.Organo
M
6

Figured it out. Instead of supplying the max value on the Y Axis as I have been, I instead implemented the afterBuildTicks callback and updated the ticks to have the correct increments.

yAxes: [{
  afterBuildTicks: function(scale) {
  scale.ticks = updateChartTicks(scale);
    return;
  },
  beforeUpdate: function(oScale) {
    return;
  },
  ticks: {  
    beginAtZero:true,
    // max:plugin.settings.maxDataValue,
    maxTicksLimit: 10
  }
}] 

my updateChartTicks function loops over the existing ticks and determines the correct increment amount between the ticks. Then I use that value to add my final "tick" which will always be greater than the largest data in the dataset.

var updateChartTicks = function(scale) {
  var incrementAmount = 0;
  var previousAmount = 0;
  var newTicks = [];
  newTicks = scale.ticks;
  for (x=0;x<newTicks.length;x++) {
    incrementAmount = (previousAmount - newTicks[x]);
    previousAmount = newTicks[x];   
  }
  if (newTicks.length > 2) {
    if (newTicks[0] - newTicks[1] != incrementAmount) {
      newTicks[0] = newTicks[1] + incrementAmount;                  
    }
  }         
  return newTicks;          
};
Makkah answered 3/7, 2017 at 16:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.