highcharts是一个十分强大的图表绘制插件,网上关于其用法有很多,不过最全的资料仍是官方api,这里通过一个动态绘制车辆速度曲线图的实例学习highcharts。
highcharts将图表表示成层级结构,例如对于曲线图,首先需要一个容器,即一个div,这个容器里有一个chart,我们可以在初始化时对这个chart进行配置,比如type属性决定了绘制图线类型,”line”为折线图,”bar”为柱状图。然后,一个chart需要有若干组数据用于绘制曲线,即series,每个series也有可选择的属性,如颜色,线宽等。最后,每个series有很多点构成,即point。除了属性,还有方法可以调用,比如chart有addSeries()方法,series有addPoint()方法。这些元素都以对象的形式存在,而series的集合和point的集合则是一个数组,所以熟悉js的话很容易掌握。
由于highcharts是基于jquery的,所以基本操作的目标都是jQurey对象。这点在使用highcharts的过程中需要注意。
jQueryObject.highcharts(option) 进行初始化,option配置内容包括chart,title,axis等。这里假设需要动态绘制不同车辆的速度曲线图,代码如下:
$('#container0').highcharts({
chart: {
type: 'line',
animation:false
},
title: {
text: '速率'
},
credits : {
enabled:false
},
xAxis: {
type:'datetime'
},
yAxis: {
title:{
text:'km/h'
}
}
});
这里注意有无option的不同。jQueryObject.highcharts(option) 是进行初始化和配置,jQueryObject.highcharts() 则是返回一个对象,可以对这个对象进行例如addSeries()的操作。
查看了一下官网的changelog,2015.12.15后highcharts用了新的构造函数Highcharts.chart(renderTo,option)。renderTo即外层div的id。现在highcharts官网上也推荐用此方式进行初始化。试比较:
var option={
chart:{
type:'line'
},
xAxis: {
type:'datetime'
},
yAxis: {
title:{
text:'km/h'
}
}
};
console.log('jQueryObject.highcharts(option):',$('#container0').highcharts(option));
console.log('jQueryObject.highcharts():',$('#container0').highcharts());
console.log('Highcharts.chart(id,option):',Highcharts.chart('container0',option));
可以看到Highcharts.chart(id,option)和jQueryObject.highcharts()返回的对象很类似,事实上,两者的__proto__属性指向同一个对象。
注意,这里没有在配置中添加series,因为假如有很多辆车并且车是动态变化的,显然用addSeries方法比在配置里完成这件任务更灵活也很简单。于是,我们可以把每辆车看成一个对象,每个对象有自己的id和name,把这些对象都放到一个集合carObject里,再遍历它们。
for(var car in carObject){
$('#container0').highcharts().addSeries({
id:carObject[car]['id'],
name:carObject[car]['name']
});
}
之前说了,$(‘#container0’).highcharts()和Highcharts.chart(‘container0’,option)返回的是对象,可以看成之前说的层级结构中的chart。它们都有addSeires()方法,所以以下方式添加曲线也可以,这也是官网推荐的方法:
var chart=Highcharts.chart('container0',option);
for(var car in carObject){
chart.addSeries({
id:carObject[car]['id'],
name:carObject[car]['name']
});
}
现在有了若干条曲线,当后台发送来数据时,需要对不同的曲线更新不同的数据,那么如何找到特定的series呢?我们在执行addSeries()时给了每个series一个id,利用chart的get(id)方法就可以了。当然,series是一个数组,所以series[num]也可以选定某个series。不过我们假设车辆可能是变化的,用数组可能出现混乱。
最后再说说addPoint。选定series后,series对象可以执行addPoint()方法。addPoint([data],ifRedraw,ifShift,ifAnimation)有四个参数,第一个参数是一个二维数组,为这个点的横纵坐标,第二个参数决定是否重新绘制曲线图,第三个参数决定是否平移(即右边添加一个点时,左边删除一个点,同时曲线图平移),第四个参数决定是否有动画效果。
每3秒向后台请求数据,并更新曲线图。为了保证美观,在少于20个点时不平移,大于时平移。最后代码如下:
socket.on('getSpeed',function(data){
var transtime=new Date().getTime();
for(var item in data){
if(count<20){
$('#container0').highcharts().get(item).addPoint([transtime,obj.speed],false,false,false);//redraw,shift,animation
}else{
$('#container0').highcharts().get(item).addPoint([transtime,obj.speed],false,true,false);
}
}
count++;
if(count>21) count--;
setTimeout(function(){
socket.emit("reqSpeed");
},3000);
});