Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highcharts - Keep Zero Centered on Y-Axis with Negative Values

Tags:

highcharts

I have an area chart with negative values. Nothing insanely different from the example they give, but there's one twist: I'd like to keep zero centered on the Y axis.

I know this can be achieved by setting the yAxis.max to some value n and yAxis.min to −n, with n representing the absolute value of either the peak of the chart or the trough, whichever is larger (as in this fiddle). However, my data is dynamic, so I don't know ahead of time what n needs to be.

I'm relatively new to Highcharts, so it's possible I'm missing a way to do this through configuration and let Highcharts take care of it for me, but it's looking like I'll need to use Javascript to manually adjust the y axis myself when the page loads, and as new data comes in.

Is there an easy, configuration-driven way to keep zero centered on the Y axis?

like image 213
macserv Avatar asked Jun 13 '13 12:06

macserv


4 Answers

I ended up finding a way to do this through configuration after digging even further into the Highcharts API. Each axis has a configuration option called tickPositioner for which you provide a function which returns an array. This array contains the exact values where you want ticks to appear on the axis. Here is my new tickPositioner configuration, which places five ticks on my Y axis, with zero neatly in the middle and the max at both extremes :

yAxis: {

    tickPositioner: function () {

        var maxDeviation = Math.ceil(Math.max(Math.abs(this.dataMax), Math.abs(this.dataMin)));
        var halfMaxDeviation = Math.ceil(maxDeviation / 2);

        return [-maxDeviation, -halfMaxDeviation, 0, halfMaxDeviation, maxDeviation];
    },

    ...
}
like image 78
macserv Avatar answered Oct 02 '22 15:10

macserv


I know this is an old post, but thought I would post my solution anyway (which is inspired from the one macserv suggested above in the accepted answer) as it may help others who are looking for a similar solution:

tickPositioner: function (min, max) {
            var maxDeviation = Math.ceil(Math.max(Math.abs(this.dataMax), Math.abs(this.dataMin)));
            return this.getLinearTickPositions(this.tickInterval, -maxDeviation, maxDeviation);
        }
like image 34
Venky Viswanath Avatar answered Oct 02 '22 13:10

Venky Viswanath


You can do this with the getExtremes and setExtremes methods

  • http://api.highcharts.com/highcharts#Axis.getExtremes%28%29
  • http://api.highcharts.com/highcharts#Axis.setExtremes%28%29

example:

http://jsfiddle.net/jlbriggs/j3NTM/1/

var ext = chart.yAxis[0].getExtremes();
like image 36
jlbriggs Avatar answered Oct 02 '22 14:10

jlbriggs


Here is my solution. The nice thing about this is that you can maintain the tickInterval.

  tickPositioner(min, max) {
    let { tickPositions, tickInterval } = this;
    tickPositions = _.map(tickPositions, (tickPos) => Math.abs(tickPos));
    tickPositions = tickPositions.sort((a, b) => (b - a));

    const maxTickPosition = _.first(tickPositions);
    let minTickPosition = maxTickPosition * -1;

    let newTickPositions = [];
    while (minTickPosition <= maxTickPosition) {
      newTickPositions.push(minTickPosition);
      minTickPosition += tickInterval;
    }

    return newTickPositions;
  }
like image 28
andy729 Avatar answered Oct 02 '22 15:10

andy729