score:22

Accepted answer

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];
    },

    ...
}

score:0

Just in case someone is searching,

One option more. I ended up in a similar situation. Follows my solution:

tickPositioner: function () {
    var dataMin,
    dataMax = this.dataMax;
    var positivePositions = [], negativePositions = [];

    if(this.dataMin<0) dataMin = this.dataMin*-1;
    if(this.dataMax<0) dataMax = this.dataMax*-1;

    for (var i = 0; i <= (dataMin)+10; i+=10) {
        negativePositions.push(i*-1)
    }

    negativePositions.reverse().pop();

    for (var i = 0; i <= (dataMax)+10; i+=10) {
        positivePositions.push(i)
    }

    return negativePositions.concat(positivePositions);

},

http://jsfiddle.net/j3NTM/21/

score:0

It is an old question but recently I have had the same problem, and here is my solution which might be generalized:

const TICK_PRECISION = 2;
const AXIS_MAX_EXPAND_RATE = 1.2;

function setAxisTicks(axis, tickCount) {
    // first you calc the max from the data, then multiply with 1.1 or 1.2 
    // which can expand the max a little, in order to leave some space from the bottom/top to the max value. 
    // toPrecision decide the significant number.
    let maxDeviation = (Math.max(Math.abs(axis.dataMax), Math.abs(axis.dataMin)) * AXIS_MAX_EXPAND_RATE).toPrecision(TICK_PRECISION);

    // in case it is not a whole number
    let wholeMaxDeviation = maxDeviation * 10 ** TICK_PRECISION;

    // halfCount will be the tick counts on each side of 0
    let halfCount = Math.floor(tickCount / 2);

    // look for the nearest larger number which can mod the halfCount
    while (wholeMaxDeviation % halfCount != 0) {
        wholeMaxDeviation++;
    }

    // calc the unit tick amount, remember to divide by the precision
    let unitTick = (wholeMaxDeviation / halfCount) / 10 ** TICK_PRECISION;

    // finally get all ticks
    let tickPositions = [];
    for (let i = -halfCount; i <= halfCount; i++) {
        // there are problems with the precision when multiply a float, make sure no anything like 1.6666666667 in your result
        let tick = parseFloat((unitTick * i).toFixed(TICK_PRECISION));
        tickPositions.push(tick);
    }
    return tickPositions;
}

So in your chart axis tickPositioner you may add :

tickPositioner: function () {
    return setAxisTicks(this, 7);
},

score:1

You can do this with the getExtremes and setExtremes methods

example:

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

var ext = chart.yAxis[0].getExtremes();

score:1

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;
  }

score:3

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);
        }

Related Query

More Query from same tag