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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 08:47:39