如何实现跨多个Highcharts图表的拖拽式范围选择导航器
问题描述
需要在多个Highcharts图表上实现一个可全局拖拽的导航器,用于高亮展示选中区间内的图表内容,效果参考下图:
查阅Highcharts官方配置项后未找到可直接实现该效果的选项,需要确认可行的实现思路,若有支持该效果的其他前端图表库也可作为备选方案。
以下是目前已编写的测试代码:
现有测试代码
JavaScript 逻辑
(function(H) { H.wrap(H.Chart.prototype, 'zoom', function(proceed, event) { var navMin = event.xAxis[0].min, navMax = event.xAxis[0].max; H.each(Highcharts.charts, function(chart) { if (chart.userOptions.chart.customNavigator) { chart.xAxis[0].setExtremes(navMin, navMax); } }); }); }(Highcharts)); $.getJSON('https://demo-live-data.highcharts.com/aapl-c.json', function(data) { var newMin = data[0][0], newMax = data[data.length - 1][0]; Highcharts.stockChart('container-main', { chart: { customNavigator: true, type: 'area', }, title: { text: '' }, credits: { enabled: false }, rangeSelector: { enabled: false }, navigator: { enabled: false }, scrollbar: { enabled: false }, xAxis: { labels:{ enabled:false }, minorTickLength:0, minorTicks:false, tickLength:0 }, series: [{ name: 'AAPL', data: data, tooltip: { valueDecimals: 2 } }] }); Highcharts.stockChart('container-main1', { chart: { customNavigator: true, type: 'area', }, title: { text: '' }, credits: { enabled: false }, rangeSelector: { enabled: false }, navigator: { enabled: false }, scrollbar: { enabled: false }, xAxis: { labels:{ enabled:false }, minorTickLength:0, minorTicks:false, tickLength:0 }, series: [{ name: 'AAPL', data: data, tooltip: { valueDecimals: 2 } }] }); Highcharts.stockChart('container-main2', { chart: { customNavigator: true, type: 'area', }, title: { text: '' }, credits: { enabled: false }, rangeSelector: { enabled: false }, navigator: { enabled: false }, scrollbar: { enabled: false }, xAxis: { labels:{ enabled:false }, minorTickLength:0, minorTicks:false, tickLength:0 }, series: [{ name: 'AAPL', data: data, tooltip: { valueDecimals: 2 } }] }); Highcharts.stockChart('container-navigator', { chart: { height: 600, zoomType: 'x', backgroundColor: 'transparent' }, credits: { enabled: false }, navigator: { enabled: true, height:540, opposite:true, maskInside:false }, rangeSelector: { enabled: true }, scrollbar: { enabled: false }, xAxis: { min: newMin, max: newMax, labels:{ enabled:false }, minorTickLength:0, minorTicks:false, tickLength:0 }, yAxis: { visible: false }, series: [] }); });
CSS 样式
#container { height: 200px; min-width: 200px; } #container-navigator{ position:absolute; top:0; width:100% }
HTML 结构
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://code.highcharts.com/stock/highstock.js"></script> <script src="https://code.highcharts.com/stock/modules/data.js"></script> <div id="container-main" style="height: 200px; min-width:200px"></div> <div id="container-main1" style="height: 200px; min-width:200px"></div> <div id="container-main2" style="height: 200px; min-width:200px"></div> <div id="container-navigator"></div>
实现方案
现有代码的核心思路可行,不需要更换图表库,补全以下逻辑即可实现目标效果:
- 移除对
H.Chart.prototype.zoom方法的重写,改为监听导航器图表x轴的afterSetExtremes事件,仅当事件由导航器拖拽/缩放触发时,将当前选中区间的min、max值同步给所有业务图表,调用setExtremes更新业务图表的显示范围。 - 调整导航器遮罩样式:将选中区间的遮罩设为完全透明,非选中区间的遮罩设为半透明黑色,同时调整导航器DOM位置,不要用绝对定位硬覆盖在业务图表上方,改为和业务图表同高度并列放置,即可实现跨图表的区间高亮效果。
- 初始化时统一所有业务图表和导航器的x轴初始范围,避免首次加载时区间不同步。
- 如果需要支持业务图表自身缩放操作反向同步导航器,给业务图表也添加
afterSetExtremes监听即可,注意加更新锁标记,避免双向同步触发循环更新。
核心同步逻辑参考:
// 导航器区间变更时同步所有业务图表 navChart.xAxis[0].update({ events: { afterSetExtremes: function(e) { if (e.trigger === 'navigator') { mainCharts.forEach(chart => { chart.xAxis[0].setExtremes(e.min, e.max, true, false); }) } } } })
内容的提问来源于stack exchange,提问作者Jignesh Kheni
相关产品推荐
相关产品推荐

