Highcharts堆叠面积图:仅在鼠标跨区域边界时更新Tooltip
实现堆叠面积图仅在区域边界切换Tooltip的方案
我明白你的需求——默认的Highcharts堆叠面积图会根据鼠标到区域的距离提前切换Tooltip,但你希望只有当光标真正穿过两个区域的边界线时才更新。要实现这个效果,我们需要绕开默认的跟踪逻辑,手动监听鼠标事件并判断当前所在的区域,只有当区域发生变化时才触发Tooltip更新。
核心思路
- 关闭默认的鼠标跟踪和自动Tooltip触发,避免默认逻辑干扰
- 监听鼠标移动事件,计算当前鼠标位置对应的堆叠区域
- 仅当鼠标从一个区域切换到另一个区域时,手动显示对应系列的Tooltip
- 监听鼠标移出事件,隐藏Tooltip
完整代码实现
// 初始化图表 const chart = Highcharts.chart('container', { chart: { type: 'area', // 绑定鼠标移动和移出事件 events: { mousemove: function(e) { handleMouseMove(this, e); }, mouseout: function() { this.tooltip.hide(); lastActiveSeries = null; } } }, xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] }, tooltip: { enabled: false, // 禁用默认Tooltip触发逻辑 // 自定义Tooltip内容格式 formatter: function() { return `<b>${this.series.name}</b><br/>${this.x}: ${this.y}`; } }, plotOptions: { series: { stacking: 'normal', trackByArea: false, // 关闭默认区域跟踪逻辑 enableMouseTracking: false // 关闭默认鼠标事件监听 } }, series: [ { name: 'Series 1', data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4] }, { name: 'Series 2', data: [144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4, 29.9, 71.5, 106.4, 129.2] } ] }); // 记录上一次激活的系列,用于判断是否需要切换Tooltip let lastActiveSeries = null; function handleMouseMove(chart, e) { // 标准化鼠标位置,获取相对于图表容器的坐标 const normalizedEvent = chart.pointer.normalize(e); // 将鼠标x坐标转换为对应的x轴数据索引 const xIndex = chart.xAxis[0].toValue(normalizedEvent.chartX); // 如果鼠标超出x轴范围,直接返回 if (xIndex < 0 || xIndex >= chart.xAxis[0].categories.length) return; // 计算堆叠后每个系列的y轴像素范围 let cumulativeY = 0; let activeSeries = null; const mouseY = normalizedEvent.chartY; chart.series.forEach(series => { const pointY = series.data[xIndex].y; // 转换数据值为图表像素坐标(注意Highcharts y轴从上到下数值递增) const bottomY = chart.yAxis[0].toPixels(cumulativeY); const topY = chart.yAxis[0].toPixels(cumulativeY + pointY); // 判断鼠标是否落在当前系列的堆叠区间内 if (mouseY >= topY && mouseY <= bottomY) { activeSeries = series; } // 更新累加值,用于计算下一个系列的堆叠边界 cumulativeY += pointY; }); // 仅当当前激活系列与上一次不同时,才更新Tooltip if (activeSeries && activeSeries !== lastActiveSeries) { const targetPoint = activeSeries.data[xIndex]; chart.tooltip.refresh(targetPoint); lastActiveSeries = activeSeries; } }
<script src="https://code.highcharts.com/highcharts.js"></script> <div id="container" style="height: 400px"></div>
关键代码解释
- 禁用默认逻辑:通过
enableMouseTracking: false和trackByArea: false彻底关闭Highcharts自带的鼠标跟踪,避免默认的“距离优先”切换逻辑干扰 - 坐标转换:使用
chart.pointer.normalize()、xAxis.toValue()和yAxis.toPixels()完成鼠标坐标与图表数据坐标的双向转换,精准定位鼠标所在的堆叠区域 - 区间判断:遍历所有系列,基于堆叠累加值计算每个系列的像素边界,判断鼠标是否落在该区间内
- 切换控制:通过
lastActiveSeries记录上一次激活的系列,只有当鼠标切换到新区域时才触发Tooltip更新,确保仅在穿越边界时才切换
这样就能实现你想要的交互效果:只有当光标真正从一个区域跨越到另一个区域的边界线时,Tooltip才会更新。
内容的提问来源于stack exchange,提问作者Mikhail Shabrikov
相关产品推荐
相关产品推荐

