Highstock图表时间显示异常及数据消失问题求助
最近我用Highcharts做温度监控图表,从MySQL拉取数据的时候碰到两个棘手的问题,折腾了好久没搞定,来跟大家聊聊:
- 加载全量数据时,X轴时间只显示年份,完全看不到时分秒
- 切换到查看最新数据时,时间格式倒是正常显示
%H:%M:%S了,但图表的线条和数据点直接消失了
先给大家看下我的核心代码和MySQL数据示例:
MySQL表数据示例(ID、UNIX毫秒时间戳、温度):
748 1521546599000 27.30
749 1521546629000 27.31
750 1521546659000 ...
我的Highcharts代码:
chart = new Highcharts.stockChart({ chart: { renderTo : 'container', type: 'spline', events: { load: function () { this.setTitle(null, { text: 'Built chart in ' + (new Date() - start) + 'ms' }); } } }, xAxis: { type: 'datetime', dateTimeLabelFormats: { // 原本只想显示时分秒,没配置其他层级 second: '%H:%M:%S' }, title: { text: 'Date' } }, yAxis: { opposite: false, title: { text: 'Temperature (°C)' } }, subtitle: { text: 'Built chart in ...' // 预留动态副标题位置 }, series: [{ name: 'Temperature', data: (function () { var data = []; // 从数组组装数据,NbRow是数据总行数 for (var i = 0; i <= NbRow; i ++) { data.push([ date_array[i], temp_array[i] ]); } return data; }()), marker: { enabled: true, radius: 2 }, tooltip: { valueDecimals: 2, valueSuffix: '°C' } }] });
注:temp_array存温度数值,date_array是转成本地时间的UNIX毫秒数组。我试过改dateTimeLabelFormat、加rangeSelector,都没解决问题。
问题拆解与解决办法
1. 全量加载时X轴只显示年份
后来才搞明白,Highcharts的时间轴标签是自动根据数据时间跨度适配的!我只配置了second级别的格式,但当全量数据的时间跨度很大(比如超过一天),Highcharts会自动切换到更高层级的时间格式(比如年、月),而这些层级我没配置,就显示默认的年份了。
解决办法:
要么把所有可能用到的时间格式层级都配置完整:
xAxis: { type: 'datetime', dateTimeLabelFormats: { second: '%H:%M:%S', minute: '%H:%M', hour: '%H:%M', day: '%m-%d', week: '%m-%d', month: '%Y-%m', year: '%Y' }, title: { text: 'Date' } }
要么强制固定显示时分秒,关闭自动适配,手动设置刻度间隔和标签格式化:
xAxis: { type: 'datetime', tickInterval: 30000, // 对应我的数据每30秒一条(看MySQL示例) labels: { rotation: 45, // 旋转标签避免重叠 formatter: function() { return Highcharts.dateFormat('%H:%M:%S', this.value); } }, title: { text: 'Date' } }
2. 查看最新数据时线条消失
这个问题我排查了好久,最后发现是数据数组的循环问题!
我的循环条件是i <= NbRow,但NbRow其实是数组的长度,数组索引从0开始,当i = NbRow时,取到的date_array[i]和temp_array[i]都是undefined,这会导致Highcharts无法解析数据,直接不渲染线条。
解决办法:
把循环条件改成i < NbRow:
for (var i = 0; i < NbRow; i ++) { data.push([ date_array[i], temp_array[i] ]); }
另外还有几个额外排查点,大家也可以试试:
- 切换最新数据后,在浏览器控制台打印
date_array和temp_array,确认数组里有合法的数值(时间戳是数字,温度是数字) - 确保数据是按时间升序排列的,Highcharts的时间序列数据必须是递增的,否则会渲染异常
- 如果用的是
stockChart,可以显式配置rangeSelector,帮助控件正确识别数据范围:
rangeSelector: { selected: 0, // 默认显示最近1小时 buttons: [{ type: 'hour', count: 1, text: '1H' }, { type: 'day', count: 1, text: '1D' }, { type: 'all', text: 'All' }] }
最后小技巧
碰到图表渲染问题,第一时间打开浏览器控制台看报错信息!比如如果有Uncaught TypeError,能快速定位到是数据格式错误还是循环越界的问题,比瞎试效率高多了。
内容的提问来源于stack exchange,提问作者Eyrag Streckeisen

