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

Angular 12中如何实现Highcharts图表的横向与纵向同步?

Angular 12 多Highcharts图表双向同步问题

我在Angular 12中实现多个Highcharts图表的横向与纵向双向同步,目前纵向同步已完成,但横向同步无法实现。当前代码仅能实现纵向同步,我定义了包含图表数据的activity对象,在ngOnInit中遍历生成图表配置;HTML里给图表容器绑定了mousemove、touchmove和touchstart事件来调用addHighlight方法。图表按行排列,希望鼠标/光标移动时,所有图表的十字准线(crosshair)能同步联动。


HTML代码

<div>
    <div (mousemove)="addHighlight($event)"
         (touchmove)="addHighlight($event)"
         (touchstart)="addHighlight($event)">
        <highcharts-chart [Highcharts]="highcharts"
                          [options]="chartOptions1"
                          style="width: 100%; min-height: 228px; display: block;">
        </highcharts-chart>
    </div>
    <div (mousemove)="addHighlight($event)"
         (touchmove)="addHighlight($event)"
         (touchstart)="addHighlight($event)">
        <highcharts-chart [Highcharts]="highcharts"
                          [options]="chartOptions2"
                          style="width: 100%; min-height: 228px; display: block;">
        </highcharts-chart>
    </div>
    <div (mousemove)="addHighlight($event)"
         (touchmove)="addHighlight($event)"
         (touchstart)="addHighlight($event)">
        <highcharts-chart [Highcharts]="highcharts"
                          [options]="chartOptions3"
                          style="width: 100%; min-height: 228px; display: block;">
        </highcharts-chart>
    </div>
</div>

TS代码

数据定义

activity = {
    xData: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    datasets: [
        {
            name: 'Widget 1',
            data: [2.5, 3.1, 3.3, 6.2, 1.41, 1, 5, 2, 6, 3],
            type: 'line',
        },
        {
            name: 'Widget 2',
            data: [2.8, 1.5, 2.1, 2.8, 1, 7.1, 3, 2, 1, 4, 7],
            type: 'line',
        },
        {
            name: 'Widget 3',
            data: [101, 98, 103, 6.87, 15, 7.11, 6, 3, 2, 9, 1],
            type: 'line',
        },
    ],
};

图表配置与同步方法

this.activity.datasets.forEach((dataset, i) => {
    // 添加X轴值
    const data = dataset.data.map((val, j) => [this.activity.xData[j], val]);
    this.chartOptions[i] = {
        chart: {
            zoomType: 'x'
        },
        title: {
            text: dataset.name,
            align: 'left',
            margin: 0,
            x: 100,
        },
        credits: {
            enabled: false,
        },
        legend: {
            enabled: false,
        },
        xAxis: {
            crosshair: {
                width: 3,
            },
            events: {
                afterSetExtremes: (event: any) => {
                    Highcharts.charts.forEach(chart => {
                        chart?.xAxis[0].setExtremes(event.min, event.max);
                    })
                }
            },
            labels: {
                format: '{value}',
            },
        },
        yAxis: {
            crosshair: true,
            title: {
                text: null,
            },
        },
        tooltip: {
            shared: true,
            style: {
                fontSize: '12px',
            },
        },

        series: [
            {
                data: data,
                name: dataset.name,
                type: dataset.type,
                fillOpacity: 0.3,
            },
        ],
    };
});


addHighlight(e: any) {
    let point, event;
    const charts = Highcharts.charts;
    console.log(charts)
    charts.forEach((chart, index) => {
        if (chart) {
            chart = charts[index];
            // 转换为图表内部坐标
            event = chart?.pointer.normalize(e);
            console.log(event)
            // 获取悬停的数据点
            point = (chart?.series[0] as any).searchPoint(event, true);
            if (point) {
                point.highlight(e);
            }
        }
    });
}

横向同步修复方案

当前addHighlight方法的问题在于:依赖searchPoint匹配数据点,当图表数据点不完全对齐时,无法同步十字准线的横向位置;且未精准传递鼠标对应的X轴数值到所有图表。修改方式如下:

addHighlight(e: any) {
    // 获取触发事件的源图表
    const triggerChart = e.target.closest('.highcharts-container')?.highcharts;
    if (!triggerChart) return;

    // 从源图表中获取鼠标位置对应的X轴数值
    const normalizedEvent = triggerChart.pointer.normalize(e);
    const xValue = triggerChart.xAxis[0].toValue(normalizedEvent.chartX);

    // 遍历所有图表同步十字准线
    Highcharts.charts.forEach(chart => {
        if (chart && chart !== triggerChart) {
            // 计算目标图表中对应X值的像素位置
            const pixelX = chart.xAxis[0].toPixels(xValue, true);
            const simulatedEvent = {
                chartX: pixelX,
                chartY: e.chartY || 0,
                target: chart.container
            };

            // 绘制横向十字准线
            chart.xAxis[0].drawCrosshair(simulatedEvent, null);
            // 绘制纵向十字准线
            chart.yAxis[0].drawCrosshair(simulatedEvent, null);

            // 匹配对应数据点并显示tooltip
            const point = chart.series[0].searchPoint({ chartX: pixelX }, true);
            if (point) {
                point.highlight(simulatedEvent);
            }
        }
    });
}

额外注意:确保所有图表的X轴基础配置一致(如刻度范围、类型),否则十字准线会出现偏移。你已实现的afterSetExtremes同步缩放逻辑可以保留,确保X轴缩放状态一致。

内容的提问来源于stack exchange,提问作者diksha bhosale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:23:14