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

Highcharts 10.1.0对数y轴显示指数值 自定义刻度标签异常

问题说明

使用Highcharts/Highstock 10.1.0版本开发时,为logarithmic类型y轴配置自定义tickPositioner函数后,出现y轴标签显示指数值的异常,异常效果如下:
异常效果截图

问题复现代码片段如下:

const chart = Highcharts.stockChart('container', {
    rangeSelector: {
        selected: 1,
        inputBoxStyle: {
            right: '80px'
        }
    },
    yAxis: [{
        type: 'logarithmic',
        tickPositioner: function () {        
        let lowestValue = this.dataMin;
        let highestValue = this.dataMax;

        if((highestValue - lowestValue) < 5 ) {
            lowestValue = this.dataMin;
            highestValue = this.dataMax;
        } else {
            lowestValue = Math.floor((this.dataMin));
            highestValue = Math.ceil((this.dataMax));
        }

        let numberOfTicks = 5;
        let positions = [];

        // 首尾刻度固定
        if(this.isLog) {
            positions.push(Math.log(lowestValue) / Math.log(10));
        } else {
            positions.push(lowestValue);
        }

        for(let i = 1; i < numberOfTicks; i++) {
            let eachPosition = lowestValue + (((highestValue - lowestValue)/numberOfTicks) * i);

            if(this.isLog) {
                let eachPositionAsLog = Math.log(eachPosition) / Math.log(10);
                positions.push(eachPositionAsLog);
            } else {
                // 兼容多数浏览器1.005四舍五入bug,加0.00001处理,最多保留2位小数
                eachPosition = Math.round((eachPosition + 0.00001) * 100) / 100;
                positions.push(eachPosition);
            }
        }

        // 首尾刻度固定
        if(this.isLog) {
            positions.push(Math.log(highestValue) / Math.log(10));
        } else {
            positions.push(highestValue);
        } 
        console.log( positions )
        return positions;
    }
    }],
    series: [{
        name: 'USD to EUR',
        data: usdeur
    }],

    exporting: {
        chartOptions: {
            chart: {
                width: 1024,
                height: 768
            }
        }
    }
});

document.getElementById('button').addEventListener('click', () => {
    chart.exportChart();
});

期望实现的效果:
期望效果截图

自行排查确认:自定义tickPositioner计算返回的刻度位置数组完全正确,问题出在highstock.js内部渲染逻辑,计算得到的正确刻度点没有被正确渲染为轴标签,无法定位具体根因。


根因分析

问题出在自定义tickPositioner的返回值逻辑错误:
Highcharts 对数轴的tickPositioner要求返回原始业务维度的实际数据值,不需要开发者手动做Math.log(val)/Math.log(10)的对数转换,对数坐标到像素位置的映射逻辑由框架内部自动完成。
原代码判断this.isLog后手动将刻度值转换为以10为底的对数值返回,框架会将传入的值默认当作原始数据值处理,一方面会重复做对数转换导致刻度位置偏移,另一方面这些手动计算的对数值不符合对数轴默认的10的整数次幂刻度规则,框架会自动启用指数格式渲染标签,最终出现指数值显示异常。

解决方案
  1. 移除tickPositioner中所有针对this.isLog的手动对数转换分支,无论轴类型是什么,都直接返回计算好的原始数据值作为刻度位置。修复后的tickPositioner代码如下:
tickPositioner: function () {        
    let lowestValue = this.dataMin;
    let highestValue = this.dataMax;

    if((highestValue - lowestValue) < 5 ) {
        lowestValue = this.dataMin;
        highestValue = this.dataMax;
    } else {
        lowestValue = Math.floor(this.dataMin);
        highestValue = Math.ceil(this.dataMax);
    }

    let numberOfTicks = 5;
    let positions = [];

    // 直接推入原始值,无需手动做对数转换
    positions.push(lowestValue);

    for(let i = 1; i < numberOfTicks; i++) {
        let eachPosition = lowestValue + (((highestValue - lowestValue)/numberOfTicks) * i);
        // 保留2位小数,兼容浏览器四舍五入bug
        eachPosition = Math.round((eachPosition + 0.00001) * 100) / 100;
        positions.push(eachPosition);
    }

    positions.push(highestValue);
    return positions;
}
  1. 如果修复后仍存在标签格式不符合预期的问题,可以给y轴添加自定义标签格式化规则,强制按普通数值格式渲染:
yAxis: [{
    type: 'logarithmic',
    labels: {
        formatter: function () {
            // 按需调整小数位数
            return this.value.toFixed(2);
        }
    },
    // 其余y轴配置
}]

内容的提问来源于stack exchange,提问作者Subhabrata Banerjee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 21:36:42