15

我有一个带有负值的面积图。与他们给出的示例没有什么不同,但有一个转折:我想保持零以 Y 轴为中心。

我知道这可以通过将 设置yAxis.max为某个值n-nyAxis.min来实现,其中n表示图表的峰值或谷值的绝对值,以较大者为准(如在这个小提琴中)。但是,我的数据是动态的,所以我不提前知道n需要是什么。

我对 Highcharts 比较陌生,所以我可能错过了一种通过配置来做到这一点的方法,让 Highcharts 为我处理它,但看起来我需要使用 Javascript 自己手动调整 y 轴当页面加载时,以及新数据进来时。

有没有一种简单的、配置驱动的方法来保持零在 Y 轴上的中心?

4

6 回答 6

22

在深入研究了 Highcharts API 之后,我最终找到了一种通过配置实现此目的的方法。每个轴都有一个调用配置选项tickPositioner,您可以为此提供一个返回数组的函数。此数组包含您希望刻度出现在轴上的确切值。这是我的新tickPositioner配置,它在我的 Y 轴上放置了五个刻度,中间整齐地为零,两个极端都为最大值:

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

    ...
}
于 2013-06-13T17:57:51.640 回答
3

我知道这是一篇旧帖子,但我想我还是会发布我的解决方案(灵感来自上面接受的答案中建议的一个 macserv),因为它可能会帮助其他正在寻找类似解决方案的人:

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);
        }
于 2015-01-16T20:40:00.817 回答
1

您可以使用 getExtremes 和 setExtremes 方法执行此操作

例子:

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

var ext = chart.yAxis[0].getExtremes();
于 2013-06-13T13:42:19.430 回答
1

这是我的解决方案。这样做的好处是您可以维护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;
  }
于 2016-04-14T14:12:18.477 回答
0

万一有人在搜索,

多了一个选择。我最终陷入了类似的境地。遵循我的解决方案:

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/

于 2015-11-13T17:33:58.130 回答
0

这是一个老问题,但最近我遇到了同样的问题,这是我的解决方案,可以概括:

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

因此,在您的图表轴 tickPositioner 中,您可以添加:

tickPositioner: function () {
    return setAxisTicks(this, 7);
},
于 2021-12-02T09:43:27.750 回答