根据公司的规划,要实现一个自定义的查询组件,其中包括了自定义图表,基本要求是:
1、 图表可以自定义,定义完成后保存到数据库中
2、 根据保存到数据库的图表定义正确的展现出图表,包括样式、轴、序列、查询条件、查询按钮等。
3、 数据源通过配置获取,再根据数据源,查询出数据(可能不在同一个数据库中)。
这里不关心图表定义、数据来源和图表展现时的查询条件与查询按钮等,只关注如何用Ext正确展现自定义图表的部分。
经过查看ext文档、探索、尝试,知道Ext的图表主要包括四个问题:图表本身(主要是样式)、轴、序列和store,而且轴、序列和store的设置要匹配(主要是字段要匹配)。
现在可以开始创建图表了,创建图表之前要先创建出来轴、序列和store(没有顺序):
创建轴:
createAxes:function(axisRecords){
var axes = [];
var axis;
for(var idx = 0; idx<axisRecords.length;idx++)
{
var gridStr = axisRecords[idx].get('grid');
var grid = gridStr==""?false:Ext.JSON.decode(gridStr);
var labelStr = axisRecords[idx].get('label');
var label = labelStr==''?"":Ext.JSON.decode(labelStr);
var axisField = axisRecords[idx].get('fields');
axis = {
type: axisRecords[idx].get('axisType'),
position: axisRecords[idx].get('position'),
fields: axisField,
title: axisRecords[idx].get('title'),
dashSize:axisRecords[idx].get('dashSize'),
label : label,
grid : grid
};
axes.push(axis);
}
return axes;
}
创建序列:
createSeries:function(seriesRecords){
var series = [];
var ser, labelStr, label, tipStr, tips, sourceName, xfield;
var fField ;
for(var idx=0;idx<seriesRecords.length;idx++){
fField = seriesRecords[idx].get('yField');
labelStr = seriesRecords[idx].get('label');
label = labelStr==''?"":Ext.JSON.decode(labelStr);
tipStr = seriesRecords[idx].get('tips');
tips = tipStr==''?'':Ext.JSON.decode(tipStr);
sourceName = seriesRecords[idx].get('sourceName');
xfield = seriesRecords[idx].get('xField');
xfield = xfield==null ? '' : xfield.toUpperCase();
ser = {
type: seriesRecords[idx].get('seriesType'),
axis: seriesRecords[idx].get('axis'),
highlight: true,
title : sourceName,
tips : tips,
showMarkers:true,
markerConfig:{
color: '#F00'
},
fill:seriesRecords[idx].get('fill'),
showInLegend : seriesRecords[idx].get('showLegend'),
stacked: seriesRecords[idx].get('stacked'),
xField: xfield,
yField: fField,
angleField: fField
};
if(label)
ser.label = label;
series.push(ser);
}
return series;
}
由代码可以看出,每个轴或序列都是一个json格式的对象,全部轴或序列就一个数组。
创建store:
createChartStore:function(){
var seriesRecords = Ext.getStore('ChartSeries').getRange();
var axisRecords = Ext.getStore('ChartAxes').getRange();
var fieldArr = [];
var idx, fields;
// 根据轴和序列得到要store应该包括哪些内容
for(idx = 0;idx<axisRecords.length;idx++){
fields = axisRecords[idx].get('fields');
if(fields != null)
fieldArr = Ext.Array.merge( fieldArr, fields.toUpperCase().split(','));
}
for(idx = 0;idx<seriesRecords.length;idx++){
fields = seriesRecords[idx].get('xField');
if(fields != null)
fieldArr = Ext.Array.merge( fieldArr,fields.toUpperCase().split(','));
fields = seriesRecords[idx].get('yField');
if(fields != null)
fieldArr = Ext.Array.merge( fieldArr,fields.toUpperCase().split(','));
}
// 创建store
var store = Ext.create('Ext.data.Store', {
//pageSize :pageSize,
fields:fieldArr,
proxy: {
type : 'ajax',
url : '/hummer/application/controller/run/FindChartData.action',
reader : {
type : 'json',
root : 'rows',
totalProperty : 'totalCount'
}
},
autoLoad : false
});
var pageNum = this.getOptionValue('每页数据条数');
// 加载前,获取页面参数值,配置的查询参数
store.on('beforeload', function (store, options) {
var conditionValues = Ext.getCmp('conditionForm').getForm().getValues();
var constantValue = [currentUser,currentUnit,currentYearMonth, pageNum];
var params = {queryId:queryId,paramsValue:conditionValues,constantValue:constantValue};
Ext.apply(store.proxy.extraParams, params);
});
return store;
}
剩下的问题就比较简单了,根据轴、序列和store把图表组装一下就可以了:
createChartPanel:function(btns){
var axisModels = Ext.getStore('ChartAxes').getRange();
var axes = this.createAxes(axisModels);
var mySeries = this.createSeries(Ext.getStore('ChartSeries').getRange());
var chartStyle = Ext.getStore("ChartStyle").getRange();
var pieXfield = '';
if(mySeries.length>=1 && mySeries[0]['type']=='pie'){
pieXfield = mySeries[0]['xField'];
}
var store = this.createChartStore(mySeries);
var seriesLegend = false;
var myLegend = chartStyle[0].get("legend") ;
for(var idx in mySeries){
seriesLegend = seriesLegend || (mySeries[idx]['showInLegend'] );
}
// 当没有显示位置或所有的序列都不显示图示时,不显示图示
if(myLegend == null || myLegend == 'false' || myLegend == false||myLegend=='{"position":""}' || (seriesLegend == false)){
myLegend = false;
}
else{
myLegend = (myLegend == null ||myLegend == 'null' || myLegend == '') ? {position: 'bottom'} : Ext.JSON.decode(myLegend.toLowerCase());
if(!myLegend['position'])
myLegend['position'] = 'bottom';
}
//排序的处理
var sortFields = [], sortField;
for(idx in axisModels){
fieldName = axisModels[idx].get('fields');
if(axisModels[idx].get('sortType')){ // 排序
for(var i in fieldName){
sortField = {};
sortField['property'] = fieldName[i];
sortField['direction'] = axisModels[idx].get('sortType');
sortFields.push(sortField);
}
}
}
store.sort(sortFields); // 排序
var background = chartStyle[0].get("background");
// 边框的处理
var border = chartStyle[0].get("border");
var myStyle = chartStyle[0].get("style");
var myChart = Ext.create("Ext.chart.Chart",{
id: 'chartCmp',
width:Ext.Number.from(chartStyle[0].get("width")),
height:Ext.Number.from(chartStyle[0].get("height")),
xtype: 'chart',
//autoSize:true,
background : background,
border : border,
style: myStyle ,
//tpl:'图表标题',
legend: myLegend,
theme:chartStyle[0].get("theme"),
animate: chartStyle[0].get("animate"),
resizable : chartStyle[0].get("resizable"),
//shadow: true,
store: store,
axes: axes,
series: mySeries//,
});
return myChart;
}
到现在为止,一个完整的动态图表已经创建完成了,至于放到哪个位置显示,就由你来定了。
通过这个自定义图表的创建,可以看出,Ext的对象基本都是配置格式,和json格式很像,或者说就是json格式,但这个问题我没有深入进去查看Ext的源码。