jQuery滑块联动Highcharts多Y轴垂直缩放问题求助
解决Highcharts+jQuery垂直滑块控制Y轴缩放的问题
针对你遇到的三个问题,我整理了修复后的代码,同时逐个说明解决思路:
修复后的完整代码
HTML部分
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script> <link rel="stylesheet" href="//code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script> <table width="100%"> <tr> <td width="95%"> <div id="lineChart" style="min-width: 600px; height: 500px;"></div> </td> <td width="5%" valign="top" align="center"> <select id="selectSliderUnit" style="width: 80px;"> <option value="0">ug/m^3</option> <option value="1">mtr/sec</option> <option value="2">degrees</option> </select><br><br> <div id="pSliderBar" style="height: 400px;"></div> </td> </tr> </table>
JavaScript部分
var ymax = 0.0; var pSliderUnit = 0; var chartInstance; // 保存图表实例,方便全局访问 $(function() { $('#lineChart').highcharts({ chart: { type: 'line', zoomType: 'xy' }, title: { text: '' }, credits: { enabled: false }, xAxis: { type: 'datetime', reversed: true }, yAxis: [{ minRange: 1, showEmpty: false, labels: { format: '{value}' }, title: { text: '\xB5g/m\xB3' }, plotLines: [] }, { minRange: 1, showEmpty: false, labels: { format: '{value}' }, title: { text: 'mtr/sec' }, opposite: true, plotLines: [] }, { minRange: 1, showEmpty: false, labels: { format: '{value}' }, title: { text: 'degrees' }, plotLines: [] }], series: [{ type: 'spline', name: 'Value 1', yAxis: 0, tooltip: { valueSuffix: '\xB5g/m\xB3' }, data: [ [Date.UTC(2018, 4, 14, 16, 20, 0), 20.4], [Date.UTC(2018, 4, 14, 16, 30, 0), 17.6], [Date.UTC(2018, 4, 14, 16, 40, 0), 18.8], [Date.UTC(2018, 4, 14, 16, 50, 0), 18.9] ] }, { type: 'spline', name: 'Value 2', yAxis: 0, tooltip: { valueSuffix: '\xB5g/m\xB3' }, data: [ [Date.UTC(2018, 4, 14, 16, 20, 0), 11.2], [Date.UTC(2018, 4, 14, 16, 30, 0), 10.5], [Date.UTC(2018, 4, 14, 16, 40, 0), 11.2], [Date.UTC(2018, 4, 14, 16, 50, 0), 10.9] ] }, { type: 'spline', name: 'Value 3', yAxis: 0, tooltip: { valueSuffix: '\xB5g/m\xB3' }, data: [ [Date.UTC(2018, 4, 14, 16, 20, 0), 5.71], [Date.UTC(2018, 4, 14, 16, 30, 0), 5.77], [Date.UTC(2018, 4, 14, 16, 40, 0), 5.69], [Date.UTC(2018, 4, 14, 16, 50, 0), 5.91] ] }, { type: 'spline', name: 'Value 4', yAxis: 0, tooltip: { valueSuffix: '\xB5g/m\xB3' }, data: [ [Date.UTC(2018, 4, 14, 16, 20, 0), 3.07], [Date.UTC(2018, 4, 14, 16, 30, 0), 3.04], [Date.UTC(2018, 4, 14, 16, 40, 0), 3.03], [Date.UTC(2018, 4, 14, 16, 50, 0), 3.03] ] }, { type: 'spline', name: 'Wind Speed', yAxis: 1, tooltip: { valueSuffix: 'mtr/sec' }, data: [ [Date.UTC(2018, 4, 14, 16, 20, 0), 0.5], [Date.UTC(2018, 4, 14, 16, 30, 0), 0.4], [Date.UTC(2018, 4, 14, 16, 40, 0), 0.2], [Date.UTC(2018, 4, 14, 16, 50, 0), 0.1] ] }, { type: 'spline', name: 'Wind Direction', yAxis: 2, tooltip: { valueSuffix: 'degrees' }, data: [ [Date.UTC(2018, 4, 14, 16, 20, 0), 170.0], [Date.UTC(2018, 4, 14, 16, 30, 0), 90.0], [Date.UTC(2018, 4, 14, 16, 40, 0), 130.0], [Date.UTC(2018, 4, 14, 16, 50, 0), 65.0] ] }] }, function(chart) { chartInstance = chart; // 保存图表实例 initSlider(); // 初始化滑块 }); // 初始化滑块的通用方法 function initSlider() { var targetAxis = chartInstance.yAxis[pSliderUnit]; $("#pSliderBar").slider({ range: true, orientation: "vertical", min: targetAxis.min, max: targetAxis.max, values: [targetAxis.min, targetAxis.max], slide: function(event, ui) { targetAxis.setExtremes(ui.values[0], ui.values[1], false); // false避免触发afterSetExtremes循环 chartInstance.redraw(); // 手动重绘 } }); // 先移除所有Y轴的afterSetExtremes事件,避免重复绑定 chartInstance.yAxis.forEach(axis => { axis.removeEvent('afterSetExtremes', updateSliderOnAxisChange); }); // 给当前选中的Y轴绑定afterSetExtremes事件 targetAxis.addEvent('afterSetExtremes', updateSliderOnAxisChange); } // 当Y轴极值变化时更新滑块 function updateSliderOnAxisChange(e) { if (chartInstance.yAxis.indexOf(this) === pSliderUnit) { $("#pSliderBar").slider("values", [e.min, e.max]); } } // 下拉选择器切换事件 $('#selectSliderUnit').change(function() { pSliderUnit = parseInt(this.value); initSlider(); // 重新初始化滑块,更新范围和绑定事件 }); });
逐个问题的解决思路
1. 切换下拉选择器时滑块范围未刷新
之前的代码只在图表初始化时创建了滑块,切换Y轴时没有更新滑块的min、max和当前值。现在我们把滑块初始化逻辑抽成initSlider()方法,每次切换下拉时调用这个方法,重新设置滑块的参数,同时重新绑定当前Y轴的afterSetExtremes事件。
2. 隐藏折线时抛出'Uncaught TypeError'异常
这个问题的根源是之前所有Y轴都绑定了afterSetExtremes事件,且都会操作同一个滑块。当隐藏系列时,非当前选中的Y轴极值变化也会触发事件去更新滑块,导致Highcharts内部交互冲突。现在我们改为:
- 每次切换Y轴时,先移除所有Y轴的
afterSetExtremes事件 - 只给当前选中的Y轴绑定事件,并且在事件中判断当前Y轴是否是选中的索引,避免无效操作
- 在滑块的
slide事件中调用setExtremes时加上false参数,避免触发afterSetExtremes事件造成循环更新
3. 缩放图表时滑块回到两端位置
同样是因为之前所有Y轴的afterSetExtremes都更新滑块,缩放图表时其他Y轴的极值变化会覆盖滑块的值。现在只有当前选中的Y轴触发afterSetExtremes时才更新滑块,就不会出现被其他Y轴极值覆盖的情况了。
内容的提问来源于stack exchange,提问作者AL滩坛I
相关产品推荐
相关产品推荐

