
本文详解如何在 highcharts/highstock 中为包含时间、数值及附加差值(如 `value2`)的三维数据点(`[x, y, value2]`)在 tooltip 中准确显示 `value2`,关键在于理解 `pointformatter` 中 `this` 的上下文并正确索引原始数据。
在使用 Highcharts 或 Highstock 绘制多指标金融图表(如股价 + EMA)时,常需在 tooltip 中同时展示主值、计算值(如百分比变化)以及数据库中预存的辅助字段(例如 value2,代表与前一周期的差值)。你提供的数据格式为 [timestamp, value, value2],但原代码中 this.series.userOptions.data[this.point.index][1] 报错或取值异常,根本原因在于:在 pointFormatter 回调函数中,this 指向的是当前数据点(Point 对象),而非事件对象——因此 this.point 是无效属性,应直接使用 this.index 访问其在系列中的位置。
✅ 正确写法如下(已适配你的双系列结构):
tooltip: {
style: { fontSize: '18px' },
pointFormatter: function() {
const series = this.series.chart.series;
const emaPoint = series[1].points[this.index]; // 获取同时间点的EMA值(假设EMA是series[1])
const percentage = Highcharts.numberFormat(
(this.y / emaPoint.y) * 100,
2
);
// ✅ 正确提取原始三维数据中的 value2(即第2个索引项,数组下标为2)
const value2 = this.series.userOptions.data[this.index][2];
return `● ` +
`${this.series.name}: ${Highcharts.numberFormat(this.y, 2)}
` +
`vs EMA: ${percentage}%
` +
`Δ from prev: ${Highcharts.numberFormat(value2, 3)}`;
}
}? 关键要点说明:
- this.index 是当前点在其所属系列中的数组索引(从 0 开始),可安全用于访问 userOptions.data;
- this.series.userOptions.data 是你传入的原始 JavaScript 数组(如 [[1609459200000, 123.45, -0.72], ...]),因此 data[i][2] 即为 value2;
- 若需跨系列读取 value2(例如两个系列共享同一 value2),建议确保两数组中相同 index 位置的 value2 值一致(如你示例中 $dadesborsa 和 $dadesema 均含 $diferencia);
- 避免在 pointFormatter 中执行复杂计算或异步操作,保持轻量以保障 tooltip 响应性能。
? 进阶建议:
若后续需更灵活地绑定元数据(如 value2、单位、状态标识等),推荐改用 data 的对象格式(而非数组):
// PHP 端生成(注意 JSON 编码防 XSS)
$dadesborsa[] = json_encode([
'x' => $databorsa,
'y' => $valorborsa,
'value2' => $diferencia,
'customLabel' => "Diff: {$diferencia}"
]);前端则可直接访问 this.value2 或 this.options.customLabel,语义更清晰、容错性更强。
通过修正 this.index 的使用并明确数据维度含义,即可稳定、精准地在 tooltip 中呈现业务所需的全部维度信息。










