`

使用Ext创建多柱、折线统计图(动态加载数据)

    博客分类:
  • ext
阅读更多

最近一个项目里面要用统计图,我对统计图就FreeChart知道一点,对于Ext,是一点都不会。只能边学表做,边做边学吧。

先看效果图:


 这个一个根据客户类型查询出来的关于合同金额的统计图,比较简单。类型只有两种,柱也只有三个(这个不重要)

需要用到的主要的Java代码:

 

Action代码(SQL语句随便写):

SView view= (SView) dao.get(SView.class, new Integer(viewID));
if(view==null)throw new Exception(" can not find view entity by viewid, if viewid="+viewID);
String sql=view.getSelectcondition();
String datas=dao.findBySQL(sql);
req.setAttribute("datas",datas);
req.getRequestDispatcher(path).forward(req, res);

 

 DAO代码:

/**
* 获取 
* @param cls
* @param id
* @return
*/
public Object get(Class cls,Serializable id){
 try {
	return getHibernateTemplate().get(cls,id);
     } catch (RuntimeException re) {
	throw re;
     }
}

/***
* 根据原生 SQL查询
 * @param sql
 * @return
*/
public String  findBySQL(final String sql) {
	try {
		String restr="[";
		List<Object [] > result = (List<Object [] > ) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session arg0) throws HibernateException,SQLException {
					return arg0.createSQLQuery(sql).list();
				}
			});
		for (int i = 0; i < result.size(); i++) {
			Object [] objs=  result.get(i);
			if(i!=0)restr+=",";
			restr+="{";
			for (int j = 0; j < objs.length; j++) {
				if(j!=0)restr+=",";
				//restr+="'field"+j+"\":\""+objs[j]+"\"";
				if(NumberUtils.isNumber(objs[j].toString())){
					restr+="'field"+j+"':"+objs[j]+"";
				}else{
					restr+="'field"+j+"':'"+objs[j]+"'";
				}
			}
			restr+="}";
		}
		restr+="]";
		return restr;
	} catch (RuntimeException re) {
		    throw re;
	}

}

 页面上主要的JS代码:

 

1、需要引入的JS和CSS文件:

<script type="text/javascript" src="lib/Help.js"></script>
<script type="text/javascript" src="<%=path %>/js/jquery-1.4.2.js"></script>
<link rel="stylesheet" href="<%=path %>/EChart/lib/style.css" type="text/css"></link>
<link rel="stylesheet" href="<%=path %>/EChart/extlib/resources/css/ext-all.css" type="text/css"></link>
<script type="text/javascript" src="<%=path %>/EChart/extlib/ext-all.js"></script>

 

2、Ext的JS(具体配置详见官网):

<script type="text/javascript">
Ext.require('Ext.chart.*');
Ext.require([ 'Ext.layout.container.Fit', 'Ext.data.JsonStore' ]);
Ext.onReady(function() {
var store1= Ext.create('Ext.data.JsonStore', {
           fields: ['field0', 'field1', 'field2', 'field3','field4'],//自选需要几个就写几个
           data: ${datas}
//其中,data的JSON串是这个样子的:
//[{'field0':'国企','field1':3,'field2':1000500.0,'field3':220000.0,'field4':780000.0},{'field0':'私企','field1':1,'field2':100000.0,'field3':5000.0,'field4':95000.0}]
       });

	Ext.create('Ext.chart.Chart', {
	   renderTo: "main1",//显示的位置,我这里放在了ID为“main1”的DIV里,默认的是在body里面(Ext.getBody())
	   width: '95%',
           height: 600,
           minHeight: 400,
           minWidth: 550,
           hidden: false,
           maximizable: true,
           title: '${view.viewname}',
           autoShow: true,
           layout: 'fit',
	   style: 'background:#fff',
           animate: true,        //动画
           shadow: true,         //阴影
           store: store1,        //##
           legend: {            //图例:默认为false,不显示
             position: 'right'   //显示位置有四个:top、bottom、left、right
           },
           axes: [
		//左边纵坐标配置
		{
		 type: 'Numeric',  //显示图形类型
		 position: 'left', //显示位置
		fields: ['field2', 'field3','field4'],
		minimum: 0,  //如果小于这个数,图标向下(相当于设置了一个起始点)
		label: {
			renderer: Ext.util.Format.numberRenderer('0,0')
		 },
		grid: true,
		title: '${view.viewcomment}'//左边纵坐标的标题
		},
		//右边纵坐标配置
		{
               type: 'Numeric',  //显示图形类型
               position: 'right',//显示位置
               fields: ['field1'],
               minimum: 0,  //如果小于这个数,图标向下(相当于设置了一个起始点)
               label: {
                   renderer: Ext.util.Format.numberRenderer('0,0')
               },
               grid: true,
               title: '合同数量'//右边纵坐标的标题
               
           }, 
           //横坐标配置
           {
               type: 'Category',
               position: 'bottom',//显示位置
               fields: ['field0'], 
               title: '${view.viewdescript}'
              
           }],
           series: [
               {
               type: 'column',//统计图类型:柱状图
               axis: 'left',
				highlight : true,//高亮显示(鼠标移动到上面时,高亮显示)
				label : {//显示柱上面的数字,并设置样式
					display : 'insideEnd','text-anchor' : 'middle',	
					field : ['field2', 'field3','field4'],//柱上显示的数字,一一对应
					renderer : Ext.util.Format.numberRenderer('0'),
					orientation : 'vertical',
					color : '#333'
				},
				listeners : {//监听,点击时触发的事件
					"itemclick" : function(storeItem) {//点击时alert出横坐标的值(或者跳转到指定的页面)
						alert(storeItem.storeItem.get('field0'));
					}
				},
               xField: 'field0',
               yField: ['field2', 'field3','field4'],
               title:['合同金额','已收金额','未收金额']//自定义的图例名称
               },
               {
                   type: 'line',//折线
                   axis: 'right',
    				highlight : true,
    				label : {//显示柱上面的数字,并设置样式
    					display : 'insideEnd','text-anchor' : 'middle',	
    					field : ['field1'],
    					renderer : Ext.util.Format.numberRenderer('0'),
    					orientation : 'vertical',
    					color : '#333'
    				},
    				listeners : {//点击时alert出横坐标的值(或者跳转到指定的页面)
						"itemclick" : function(storeItem) {
							alert(storeItem.storeItem.get('field0'));
						}
					}, markerConfig: {
    		                type: 'circle',//折线图“点”的样式
    		                size: 4,
    		                radius: 4,
    		                'stroke-width': 0
    		            },
                   xField: 'field0',
                   yField: ['field1'],
                   title:'合同数量'//自定义的图例名称
                   }
               
           ]
       });
});
</script>

 

效果已经出来了,我需要说明的几点是我在弄这个的过程中碰到的几个让我头疼的问题:

1、柱状图不显示,就显示个折线图;

2、折线图有一个点是在横坐标以下的(类似于负数的情况);

 

去网上搜这种情况,得到的答案:值为null就是不显示的,缺失时折线图会按0处理。可是很明显,我这两种情况都不是啊(我alert了传递过来的json串,有数据)。数据没问题,那就可能是结构或类型的问题了。查了结构,很正常的JSON结构,没错。查类型,因为不知道什么类型,就去官网找例子,看类型。他们都是用静态数据演示的,数据类型一目了然:数字类型(都是数字,统计图也绝对都是数字,不然也就是失去了统计的意义了,不就是为了得到几个数字嘛)。再回头查我的JSON串([{'field0":"国企",'field1":"3",'field2":"1000500.0",'field3":"220000.0",'field4":"780000.0"},{'field0":"私企",'field1":"1",'field2":"100000.0",'field3":"5000.0",'field4":"95000.0"}]),都是双引号引起来的,无论是数字还是名称。于是改,去掉数字的双引号(也就是有了代码中数字的判断:NumberUtils.isNumber(objs[j].toString()),我知道,这个方法已经过时了),再测试,问题依旧。我把官网的静态数据粘贴上去,好着呢。那就一定是我在数据上遗漏了什么,然后再次发现,人家名称都用单引号,我还用得双引号,改,改成单引号,再测试,好了。

所以,综上所述:在拼接Ext数据仓库的JSON串时,数字都不要用引号(单双都不要用),非数字用单引号。不管能不能治病,反正治不死人。

 

3、折线图的第一个点是0,第二个点正常(为1);

4、总是有一个点为0(就是折线图从0开始,哪怕我那个点的数据大于0);

上面的问题解决了,统计图都显示出来了,也不再出现在横坐标以下了,但是第一个点总在0上,可是它的数据明明是3啊。我把我的数据仓库换成官网测试数据,嘿,它竟然也有一个是从0开始的,我又改了其他的数据,发现并不是专一的那一列为0,总是有一个为0的,这就怪了。于是查啊查,发现作为折线图的那个axes的position: 'bottom',横坐标也是bottom,按道理说我应该是让它根据右边的坐标来显示的,而不是像横坐标一样,于是换成right,也就是:position: 'right',在一刷新,正常了。换成官网的静态数据,无论怎么改,都不在从0开始了(测试数据都是大于0的数据)。

总结:在设置折线图的纵坐标的位置时,一定不要设置成bottom,否则它就从bottom的位置开始取点了。

 

5、图例问题

效果图:

我的yField都是field1,field2,field3,field4,图例就是根据这个取的,自然也就是field1/2/3了。不显示图例把,图上三个柱、两个点代表什么谁知道啊。显示吧,这field1,field2,field3除了写的人别人也不知道是什么呀。于是想着说改ext的JS,怎么改呢,不知道,搜。搜到了一篇类似的,也是改图例的(链接:http://standalone.iteye.com/blog/1074517),可是人家是用英文写的,俺看不懂啊,谷歌翻译。也不知道谷歌是不打算在大陆混了还是怎么滴,死活打不开,好不容易打开了一回,不知道什么原因我的火狐自己死了,再一打开就链接不上了,没招,只能硬着头皮看,连猜带蒙的看的差不多了,也有想法了,打算改ext.all.js。打开一看,我的IDE直接挂了,查看属性,2个多M,太大了,而且所有的代码还写在一行。得先格式化一下。网上找了个JS格式化工具,格式化了,结构挺好看的,以为可以弄了,统计图一运行,直接报错,根本就打不开统计图。不格式化了还不成吗,又换回去,统计图又看到了。这么一长行的代码(格式化之后有9万多行)找我要的legend不容易也就算了,我一打开我的IDE就得挂一回,到后来我不开它了,我复制粘贴个东西,IDE也得荡。改了内存还那样,弄得好几次尝试的代码都丢了。我的配置也不低吧,I5了,虚拟内存都设置到1024了,也不错了。哎,要是有单独的ext的chart的js包该多好啊,至少绝对没这么大啊(或许本来就有,只是我还傻傻不知道)。

 

改ext的JS宣告失败,再想一招:直接把field1、field2、field3替换成汉字,显示的时候也用汉字去查,总行吧,一试还真行,也得到了刚刚的那个效果。

 

 效果虽出来了,但这样子总觉得不太好,接着网搜,这次搜的是:extjs4.0 chart legend(前面搜的都是中文,这回咱也换英文试试),搜到了一篇没有关系的(http://blog.csdn.net/chenbin520/article/details/6666749),主要讲Ext的使用,看了,基本上都懂,没劲,就看下面的评论,竟然看到有人问我的这个问题(看来被这个问题困扰的不止我一个啊,哈哈),一看回复,哈,有结果了:在yField后面再加一个title,像代码里面的:title:['合同金额','已收金额','未收金额']要是只写一个title:['合同金额'],那么那三个柱的图例名称都是‘合同金额’(不信可以试试),(上面还有个回复是这个链接:http://jsfiddle.net/mf2jH/64/,我点进去看了,看到最后一行才找到我要找的东西)。

 

这个Ext着实不简单啦,又或者是,俺太傻了啦!嘿嘿,慢慢来吧!

  • 大小: 56.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics