Highcharts是一个非常成熟的绘制图表的前端库,由纯JS编写。能够很方便的在实际项目中添加有交互性的图表,并且免费提供给个人学习、个人网站和非商业用途使用。目前HighCharts支持的图表类型有曲线图、区域图、柱状图、饼状图、散状点图和综合图表。
HighCharts的UI设计非常优美,由于使用纯JS编写,所以不需要像Flash和Java那样需要插件才可以运行,而且运行速度较快。最重要的是,HighCharts还有很好的兼容性,能够兼容当前主流的浏览器。详细的文档,可以参考:www.highcharts.com.
下面,我将分享使用highcharts在实际项目中绘制动态曲线图的例子,先上代码:
QtAvgCostChartPanel = function() { this.plot; var scope = this; //获取Provider(应用名) var appArr2store = buildCombo.getApp(); //当Provider App默认值为search时,按search加载Service Name、Service MethodName及providerHost默认的下拉框列表 //获取ProviderHost var providerArr2store = buildCombo.getProvider('search'); //获取service(服务名) var serviceArr2store = buildCombo.getService('search'); //初始化service methodName(服务方法名) var methodArr2store = new Ext.data.ArrayStore({ fields:['methodName','methodName'] }); this.toolBar = [ '-', 'Provider App:', { id : 'providerApp_QtAvg', xtype : 'combo', width : 155, listWidth : 200, value : 'search',//设置默认值 store : appArr2store, valueField : 'appCode', displayField : 'appCode', selectOnFocus : true, mode : 'local', triggerAction : 'all', listeners:{ 'select': function(){ //选择App的值,可以级联确定service及providerHost下拉框列表 var appValue = this.getRawValue(); Ext.getCmp('providerHost_QtAvg').store.removeAll(); //清除缓存数据 Ext.getCmp('serviceName_QtAvg').store.removeAll(); //清除缓存数据 Ext.getCmp('serviceMethodName_QtAvg').store.removeAll(); //清除缓存数据 //当重新选择时,清空各下拉框显示值及原始值 Ext.getCmp('serviceName_QtAvg').clearValue(); Ext.getCmp('serviceMethodName_QtAvg').clearValue(); Ext.getCmp('providerHost_QtAvg').clearValue(); //获取service(服务名) var serviceArr2store = buildCombo.getService(appValue); //重新加载数据(local) Ext.getCmp('serviceName_QtAvg').store.loadData(serviceArr2store); //获取ProviderHost var providerArr2store = buildCombo.getProvider(appValue); //重新加载数据(local) Ext.getCmp('providerHost_QtAvg').store.loadData(providerArr2store); scope.query(); } } }, '-','Provider Host:', { id : 'providerHost_QtAvg', xtype : 'combo', width : 155, listWidth : 180, store : providerArr2store, valueField : 'hosts', displayField : 'hosts', selectOnFocus : true, mode : 'local', triggerAction : 'all', listeners:{ 'select': function(){ scope.query(); } } }, '-','Service Name:', { id : 'serviceName_QtAvg', xtype : 'combo', width : 155, listWidth : 280, store : serviceArr2store, valueField : 'service', displayField : 'service', selectOnFocus : true, mode : 'local', triggerAction : 'all', listeners:{ 'select': function(){ var appValue = Ext.getCmp('providerApp_QtAvg').getRawValue(); var selectedValue = this.getRawValue(); Ext.getCmp('serviceMethodName_QtAvg').store.removeAll(); //清除缓存数据 //当重新选择时,清空各下拉框显示值及原始值 Ext.getCmp('serviceMethodName_QtAvg').clearValue(); //获取service nameMethod(服务方法名) var methodArr2store = buildCombo.getServiceMethod(appValue,selectedValue); //重新加载数据(local) Ext.getCmp('serviceMethodName_QtAvg').store.loadData(methodArr2store); scope.query(); } } }, '-','Service MethodName:', { id : 'serviceMethodName_QtAvg', xtype : 'combo', width : 155, listWidth : 420, store : methodArr2store, valueField : 'methodName', displayField : 'methodName', selectOnFocus : true, mode : 'local', triggerAction : 'all', listeners:{ 'select': function(){ scope.query(); } } }, '-',{ iconCls : 'ms-query', xtype : 'button', text : "查找", handler : this.query, scope : this }]; this.reportPanel = new Ext.BoxComponent( { border : false, autoEl : { tag : 'div', html : "<div id='QtAvgCostChartDiv' style='width:80%;height:90%;'></div>" }, anchor : 'none -24' }); QtAvgCostChartPanel.superclass.constructor.call(this, { id : 'QtAvgCostChart', title : '平均耗时', margins : '0 0 5 5', cmargins : '0 5 5 5', closable : true, tbar : this.toolBar, bbar : this.bottomBar, layout : 'fit', autoScroll : true, items : [this.reportPanel], listeners : { 'beforedestroy' : function(){ clearInterval(this.reVal); } } }); }; Ext.extend(QtAvgCostChartPanel, Ext.Panel, { query : function() { var param = { providerApp : Ext.getCmp("providerApp_QtAvg").getRawValue(), providerHost : Ext.getCmp("providerHost_QtAvg").getRawValue(), serviceName : Ext.getCmp("serviceName_QtAvg").getRawValue(), serviceMethodName : Ext.getCmp("serviceMethodName_QtAvg").getRawValue() }; clearInterval(this.reVal); this.draw("quarterAnalystService", "getMemoMinsAvgCost" , param); }, init : function() { this.draw("quarterAnalystService", "getMemoMinsAvgCost" , {}); }, draw : function(service, method ,param){ var me = this; Highcharts.setOptions({ global : { useUTC: false } }); var chart, maxMinData = {}, params = Ext.encode({s : service, m : method, p : param}); $('#QtAvgCostChartDiv').highcharts({ chart : { type: 'spline', animation: Highcharts.svg, // don't animate in old IE marginRight: 10, events : { load : function(){ var series = this.series[0]; var loadData = function(){ maxMinData = {}; $.ajax({ type : "post", url : "ajax.do", data : {rmi : params}, async : false, success : function(response){ if(!Ext.isEmpty(response)){ var xdata = response['xdata'], ydata = response['ydata'], others = response['others']; for(var i = 0, len = xdata.length; i<len; i++){ maxMinData[xdata[i]] = others[i];//保存最大值最小值 var x = xdata[i], y = ydata[i]; var isShift = series.data.length >= 15;//防止数据过大,造成浏览器崩溃 series.addPoint([x,y], true, isShift); } } } }); } loadData();//首次加载数据 me.reVal = setInterval(loadData, 30000);//动态获取数据,并保存返回值 } } }, title : { text: '平均耗时实时监控' }, xAxis : { type: 'category' }, yAxis : { title : { text : '平均耗时/ms' }, min : 0, plotLines : [{ value : 0, width : 1, color: '#808080' }] }, tooltip : { formatter : function(){ var max_min = maxMinData[this.point.name] && maxMinData[this.point.name].split(','); if(!max_min){ return '<b>'+ this.series.name + '</b><br/>'+this.point.name+ '<br />'+'平均值 :'+this.y + '<br />'+'最大值 :'+ 0 + '<br />'+'最小值 :'+ 0 ; } return '<b>'+ this.series.name + '</b><br/>'+this.point.name+ '<br />'+'平均值 :'+this.y + '<br />'+'最大值 :'+max_min[0]+ '<br />'+'最小值 :'+max_min[1]; } }, legend : { enabled : false }, exporting : { enabled : false }, credits : { enabled : false }, series : [{ name : '平均耗时', data : [] }] }); } }); Ext.reg("QtAvgCostChart", QtAvgCostChartPanel);
上面是一个平均耗时的代码,使用了Extjs,关键的绘图代码是方法draw : function(service, method ,param){},在load事件中,使用了jquery的ajax方法同步取数据,因为后面要用到这些数据,故而使用了同步方法。其中:
var isShift = series.data.length >= 15;//防止数据过大,造成浏览器崩溃
这里是因为每次均获取15分钟的数据,故此,当图中数据大于15个,将会删除最前面的数据点。动态加载的方法是loadData,每半分钟刷新一次。效果如下: