You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Highcharts x轴负对数刻度失效求助(官方逻辑仅Y轴生效)

Highcharts对数轴负值兼容逻辑X轴失效问题修复

我知道Highcharts不建议在对数刻度中使用负值,但官方提供的兼容逻辑只对Y轴生效——切换X轴为对数刻度后,刻度位置(tickPositions)会消失,X轴无法正常渲染对数刻度,相同逻辑用在Y轴上却能正常工作。

问题根源

原代码仅绑定了afterInit事件,当通过按钮动态切换X轴类型时,轴实例不会重新初始化,而是执行更新操作,afterInit事件不会触发,导致兼容逻辑根本没作用到X轴上。

修复后的代码

function allowNegativeValues(H) {
/* eslint-disable no-underscore-dangle */
const logAdditions = H._modules['Core/Axis/LogarithmicAxis.js'].Additions.prototype;

// 把兼容逻辑抽成独立函数,方便复用
function applyNegativeLogCompatibility(axis) {
    const logarithmic = axis.logarithmic;
    if (logarithmic && axis.options.custom.allowNegativeLog) {
        axis.positiveValuesOnly = false;
        // 重写对数和线性的转换函数
        logarithmic.log2lin = num => {
            const isNegative = num < 0;
            let adjustedNum = Math.abs(num);
            if (adjustedNum < 10) {
                adjustedNum += (10 - adjustedNum) / 10;
            }
            const result = Math.log(adjustedNum) / Math.LN10;
            return isNegative ? -result : result;
        };

        logarithmic.lin2log = num => {
            const isNegative = num < 0;
            let result = Math.pow(10, Math.abs(num));
            if (result < 10) {
                result = (10 * (result - 1)) / (10 - 1);
            }
            return isNegative ? -result : result;
        };
    }
}

// 绑定初始化事件,处理首次创建的轴
H.addEvent(H.Axis, 'afterInit', function () {
    applyNegativeLogCompatibility(this);
});

// 新增绑定轴更新事件,处理动态切换类型的情况
H.addEvent(H.Axis, 'afterSetAxisOptions', function () {
    applyNegativeLogCompatibility(this);
});

// 保持原有的刻度位置计算扩展逻辑不变
H.wrap(logAdditions, 'getLogTickPositions', function (
    proceed,
    interval,
    min,
    max,
    minor
) {
    if (
        !this.axis.options.custom.allowNegativeLog ||
        interval >= 0.5 ||
        interval < 0.08
    ) {
        return proceed.call(this, interval, min, max, minor);
    }

    const log = this,
        roundedMin = Math.floor(min),
        positions = [];
    let intermediate,
        i,
        j,
        len,
        pos,
        lastPos,
        break2;

    if (interval > 0.3) {
        intermediate = [1, 2, 4];
    } else if (interval > 0.15) {
        intermediate = [1, 2, 4, 6, 8];
    } else {
        intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    }

    for (i = roundedMin; i < max + 1 && !break2; i++) {
        len = intermediate.length;
        if (i <= 0) {
            for (j = len - 1; j >= 0 && !break2; j--) {
                pos = -log.log2lin(
                    (log.lin2log(-i) || 1) * intermediate[j]
                );

                if (
                    pos > min &&
                    (!minor || lastPos <= max) &&
                    typeof lastPos !== 'undefined'
                ) {
                    positions.push(lastPos);
                }
                if (lastPos > max) {
                    break2 = true;
                }
                lastPos = pos;
            }

            if (lastPos < min || lastPos > max) {
                lastPos = undefined;
            }
        }

        if (i === 0 && min <= 0 && max >= 0) {
            positions.push(0);
        }

        if (i >= 0) {
            for (j = 0; j < len && !break2; j++) {
                pos = log.log2lin((log.lin2log(i) || 1) * intermediate[j]);

                if (
                    pos > min &&
                    (!minor || lastPos <= max) &&
                    typeof lastPos !== 'undefined'
                ) {
                    positions.push(lastPos);
                }
                if (lastPos > max) {
                    break2 = true;
                }
                lastPos = pos;
            }
        }
    }

    return positions;
});

修改说明

  • 把原有的兼容逻辑提取成applyNegativeLogCompatibility函数,避免重复代码
  • 新增绑定afterSetAxisOptions事件,确保在动态切换X轴类型(轴更新)时,兼容逻辑能被重新触发应用
  • 保留原有的刻度位置计算扩展逻辑,保证负值场景下刻度能正确生成

内容的提问来源于stack exchange,提问作者Kenny Lazer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:50:59