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

