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
相关产品推荐
相关产品推荐

