`
远去的渡口
  • 浏览: 472983 次
  • 性别: Icon_minigender_2
  • 来自: 上海转北京
社区版块
存档分类
最新评论

JfreeChart热点map的应用

阅读更多

    今天主要总结一下JfreeChart中热点map的应用,根据我个人的理解来总结的,可能会有某些地方不是很正确,如有错误,请大家指正,不断改进。

     首先,这里的热点的应用在于用户与JfreeChart图像的交互,也就是与图像文件(因为我们是将Chart对象以二进制数据写入一个图像文件了,比如PNG文件,JPEG图像文件)交互。在HTML中,为了让一个图像具有可交互的功能就必须给该图像定义一个Map对象,然后在

<img id="chartimage" src="${linechart }" usemap="#${filename }" >

也就是在img标签的usemap属性上,指定map对象。

下面举例说明,用JfreeChart在这个图像中产生热点。

 

那么它的原始map数据大致为:

<map id="jfreechart-23846.png" name="jfreechart-23846.png">

<area shape="poly" coords="675,93,681,93,681,99,675,99,675,93,675,93" title="日平均攝取熱量: (09-12-28 上午12:00, 1,788)" alt=""/>

<area shape="poly" coords="276,96,282,96,282,102,276,102,276,96,276,96" title="日平均攝取熱量: (09-11-27 上午12:00, 1,741.8)" alt=""/>

<area shape="poly"

<area shape="poly" coords="225,97,231,97,231,103,225,103,225,97,225,97" title="日平均攝取熱量: (09-11-23 上午12:00, 1,722.4)" alt=""/>

<area shape="poly" coords="115,24,114,26,112,27,110,26,109,24,110,22,112,21,114,22,115,24,115,24" title="日平均消耗熱量: (09-11-14 上午12:00, 3,027.8)" alt=""/>

</map>

这里面,shape是指热点的区域,本段中的poly是一个多边形,也有Rectangle等。Coords是这个多边形的坐标,通常是需要用工具生成,这里所展示的是JfreeChart自动生成的。Title=””中的内容便是mouse移到各个点时,展示出的信息,mouse移开后信息不再显示。这里不需要我们再写别的代码,个人理解是,浏览器可以解析这部分数据,相当于将title的内容在onmouseover中显示。

   那么,现在的问题就在于,怎么获得map数据了。

    

当然是根据一个图像来生成对应的MAP对象。

在创建一个图表对象时候有两个参数,比如这里面的折线图的部分代码:

JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(title, "",

          y, xydataset, true, true, false);

两个参数就是这个方法中的最后两个参数,这两个参数的类型都是布尔值。这两个参数意思分别是:是否创建工具提示(tooltip)以及是否生成URL。这两个参数分别对应着MAP中一个AREAtitle属性以及href属性。

可是我想知道的是怎么来产生这个MAP啊!哈哈,不要着急,JFreeChart已经帮我们做好生成MAP对象的功能。为了生成MAP对象就要引入另外一个对象:ChartRenderingInfo。因为JFreeChart没有直接的方法利用一个图表对象直接生成MAP数据,它需要一个中间对象来过渡,这个对象就是ChartRenderingInfo。下图是生成MAP数据的流程图:

 

如上图所示,ChartUtilities类是整个流程的核心,它周围的对象都是一些例如数据对象或者是文件等。这个流程简单描述如下:首先创建一个ChartRenderingInfo对象并在调用ChartUtilitieswriteChartAsJPEG时作为最后一个参数传递进去。调用该方法结束后将产生一个图像文件以及一个填充好MAP数据的ChartRenderingInfo对象,有了这个对象我们还是没有办法获取具体的MAP数据,我们还必须借助于ChartUtilitieswriteImageMap方法来将ChartRenderingInfo对象读取出来,获取MAP数据的代码片断如下:

 

JFreeChart chart = createCaloriesLineChart(timesers, weekormonth,
				title, avgenergy + "(" + y + ")", index, week, year1,year,
				nodatamess, maxcalorie, month);

		HttpServletRequest request = io.getRequest();
		String filename = "";
		String graphURL = "";

		PrintWriter writer = null;
		try {
			io.getResponse().setContentType("text/html");
			io.getResponse().setCharacterEncoding("UTF-8"); // 这里要设置一下,因为这里相当于用PrintWriter将图片写出来,如果不设置字符集,则默认为ISO-8859-1,而页面用的是UTF-8.
			writer = io.getResponse().getWriter();
			Shape shape = new Rectangle(10, 5);
			ChartEntity entity = new ChartEntity(shape);
			StandardEntityCollection coll = new StandardEntityCollection();
			coll.add(entity);
			ChartRenderingInfo info = new ChartRenderingInfo(coll);
			filename = ServletUtilities.saveChartAsPNG(chart, 720, 250, info,
					io.getSession());
			ChartUtilities.writeImageMap(writer, filename, info, true);

			graphURL = request.getContextPath() + "/displayChart?filename="
					+ filename;

			
			String strimg = ChartUtilities.getImageMap(filename, info);

 

 

当初在实现这个拿到map数据时,花费了不少时间,根据writeImageMap()回溯到找寻如何得到 info,要得到info又如何得到StandardEntityCollection对象,以及StandardEntityCollectionChartEntityShape的关联,这个就需要花时间好好研究API了,感觉JfreeChart API写的太过于简单,需要自己动手试试一些方法才可以完成,不过感觉这部分还是比较单一的需求,感觉在图象对象其他的类上,过于复杂,文档过于简单,我们必须去了解每个类型的图表对象应该对应哪些AxisPlotRenderer类,并且必须非常熟悉这些类的构造函数中每个参数的具体含义才可以少走弯路,对于某些特定的需求,比如柱状图与折线图并存时,可不可以用XYPlot,只有试过,根据报错的信息才知道这样做是不可以的。好了,别的感慨不多说了。这里的strimg的内容就是map对象。

 

自己实现响应mouse事件

上图的map热点信息,大家可以看出,过于简单、表达的方式的不常规很难满足产品的需求,至少要以比较直观的、清晰的方式来表达信息,并且,如果单单只写出XY坐标对应的值,相信map热点的存在就是多余,just a Demo.所以为了满足产品级别需求,我们需要自己实现响应mouse事件。

   这个解决方案有多种,我是根据自己的理解,将很规则的map数据解析,根据X轴时间取到关联这一天、周、月的详细信息,然后将解析、重组后的数据以变量传到onmouseover事件中。

当然,怎么样让数据与map中各<area>标签的内容一致,以及后续的Tip定位问题,也是需要考虑的。为了方便,这里需要给每个area节点再加一个属性id,并赋值。

StringReader reader = new StringReader(strimg);
			InputSource source = new InputSource(reader);
			SAXBuilder build = new SAXBuilder();

			try {
				Document doc = build.build(source);
				Element element = doc.getRootElement();

				List<Element> list = element.getChildren();

				int size1 = list.size();
				for (int j = 0; j < size1; j++) {

					String nstr = "";

					Element e = list.get(j);
					Attribute att = e.getAttribute("title");
					String value = att.getValue();
					value = value.replace("(", "");
					value = value.replace(")", "");

					Attribute bute = new Attribute("id", j + "");
					e.setAttribute(bute);

					int id = bute.getIntValue();

					int ind = j;
					if (j >= size1 / 2) {
						ind = j - (size1 / 2);
					}

					UserFoodRecordBean r = (UserFoodRecordBean) calories
							.get(ind);

					double bike = r.getBikeCalorie();
					double bmrto = r.getBmrTotal();
					double sport = r.getSpcal();
					double foodcal = r.getCaloriesimple();
					double fect=r.getFoodfec();
					double cyclomer=r.getCycal();
					double total1 = r.getSportTotalCalorie();
					double balance = foodcal - total1;
					double dailywork = r.getDailyworkcalorie();
					String datestr = r.getUserfoodDate();

					if (weekormonth == 0) {
						datestr = BarChartData.formAtDate(datestr);
					} else {
						String[] das = datestr.split("-");
						int weekindex = Integer.parseInt(das[1]);

						if (weekormonth == 1) {
							
							datestr = das[0] + year + index1 + weekindex + week;
						} else {
							datestr = das[0] + year1  + weekindex + month;

						}
					}

					balance = Double.parseDouble(BarChartData
							.formAtCalorie(balance));

					nstr += "date=" + datestr + "&BMR=" + bmrto + "&";
					if (bike > 0) {
						nstr += "e-Bike=" + bike + "&";
					}
					if (sport > 0) {
						nstr += "sport=" + sport + "&";
					}
					if(cyclomer>0){
						nstr+="cyclemer="+cyclomer+"&";
					}
					if(fect>0){
						nstr+="fect="+fect+"&";
					}

					nstr += "food=" + foodcal + "&" + "total=" + total1
							+ "&balance=" + balance + "&dailywork=" + dailywork;

					// nstr=HtmlUtils.htmlUnescape(nstr);

					att.setValue("");// set nstr to title

					String over = "showChartTips('" + nstr + "','" + id
							+ "',event);";
					String out = "chartlivess();";

					Attribute bu = new Attribute("onmouseover", over);

					e.setAttribute(bu);

					Attribute outatt = new Attribute("onmouseout", out);
					e.setAttribute(outatt);

				}

				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				PrintWriter pw = new PrintWriter(baos); // 用PrintWriter可以解决生成编码为UTF-8格式的XML内容出现中文乱码的问题


				Format format = Format.getPrettyFormat();
				format.setEncoding("UTF-8");

				XMLOutputter output = new XMLOutputter();
				output.setFormat(format);

				output.output(doc, pw);

				String strs = baos.toString();
				int j = strs.indexOf("<map");
				strs = strs.substring(j);
				io.setData("intakemap", strimg, BeanShare.BEAN_SHARE_REQUEST);

				

			} catch (JDOMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

 

 

 

 

然后以什么样式展示就与自己的审美有关了……当然可以是美工提供模版,呵

具体的过程就不用累赘了。

看看这样实现后的效果:

 

另外,在实现的过程中,还有一个问题也是花了许多时间 tip的定位问题,要兼容IE6IE7IE8FireFox,并且,出现滚动条时tip可能会错位问题,部分代码如下:

 

 var area= document.getElementById(id);
   if(area){
      var scroleft=document.documentElement.scrollLeft;
      var left=e.clientX+scroleft;
      var topy=e.clientY;
      var top= document.documentElement.scrollTop + topy;
  
  left-=66;
   
    var _tips=createTip1(); 
      _tips.style.width ="27em";
     // _tips.style.height="190px";
      _tips.style.display= ""; 
      
      _tips.style.left = left+"px";    
      _tips.style.top = top+"px"; 
  _tips.innerHTML=document.getElementById("tipmess").innerHTML;
  
   if(navigator.userAgent.indexOf('Firefox') >= 0){
    top=window.scrollY + e.clientY;
    left=window.scrollX+e.clientX;
    _tips.style.left=left+"px";
      _tips.style.top = top+"px"; 
      }
   
  
  }

 

 

PS: 部分内容转自http://www.ibm.com/developerworks/cn/java/l-jfreechart/ 作者 刘冬

 如果大家之前没有接触过JfreeChart或者是初学者,可以先看看这篇文章 。当初我在实现这个热点map时,感觉这篇文章写的很详细,对我也很有帮助,不过,我实现的具体方案还是经过多次尝试、多次调整,毕竟我这里的要求更高,呵呵

分享到:
评论
1 楼 happydrive 2010-08-21  
楼主,我看了之后还是有点迷茫,能上点完整的代码。

相关推荐

    MyBatis高级查询+JFreeChart热点

    【标题】"MyBatis高级查询+JFreeChart热点"是一个综合的学习项目,它涵盖了数据库操作和数据可视化两个重要领域。MyBatis是Java开发中常用的一个持久层框架,而JFreeChart则是一个用于创建高质量图表的库。下面将...

    jfreechart 折线图 应用

    本程序是把图片保存到本地,当然实际应用中,只要在程序和页面中做相关配置即可以使用。 因为图片带点透明,所以windows查看的时候,会根据背景色,颜色有所不同,或是黑色,或是黄色,当配置到网页上,返回到页面...

    JFreeChart报表的应用

    JFreeChart是一个强大的Java库,用于创建各种图表,如柱状图、饼图、线图等,而Struts框架则是一个成熟的MVC(模型-视图-控制器)架构,常用于构建Web应用。将JFreeChart与Struts结合,可以实现动态生成报表,特别是...

    JFreeChart 在 web中的应用

    JFreeChart 在 web中的应用JFreeChart 在 web中的应用JFreeChart 在 web中的应用JFreeChart 在 web中的应用JFreeChart 在 web中的应用

    jfreeChart 的图表应用

    **JFreeChart 图表应用详解** JFreeChart 是一个用于Java平台的开源图表库,它提供了丰富的图表类型,包括柱状图、饼图、线形图、散点图、甘特图、时间序列图等,使得开发者能够方便地在应用程序中生成高质量的图形...

    Spring+JFreeChart 自动生成统计图

    这篇文章可能是介绍如何在Spring应用中集成JFreeChart,以便为数据可视化提供服务。 JFreeChart是一个强大的Java库,能够创建多种类型的图表,包括折线图、柱状图、饼图、散点图等,非常适合用于报表和数据分析应用...

    JFreeChart在JSP中的应用实例

    ### JFreeChart在JSP中的应用实例 #### 一、JFreeChart简介 JFreeChart是一款功能强大且灵活的开源Java图表库,它为开发者提供了丰富的API来创建各种类型的图表,如折线图、柱状图、饼图等。由于其良好的可定制性...

    jfreechart简单应用实例

    **JFreeChart 简单应用实例** JFreeChart 是一个强大的开源 Java 图形库,专为生成高质量的图表而设计。它广泛应用于各种 Java 应用程序中,包括报表、数据分析、以及可视化数据。本实例将帮助你理解 JFreeChart 的...

    JFreeChart使用心得+列子

    JFreeChart是一款强大的Java图表库,它允许开发者创建各种复杂的图表,如柱状图、饼图、线图、散点图等,广泛应用于数据分析、报告展示以及Web应用程序中。本文将分享JFreeChart的使用心得,并提供一个在Web应用下的...

    jfreechart-1.0.9源码及例子

    JFreeChart,一个强大的开源Java图表库,是开发复杂数据可视化应用的重要工具。版本1.0.9在提供丰富的图表类型和高度定制性方面表现出色,是许多Java开发者首选的图形绘制框架。本文将深入探讨JFreeChart 1.0.9的...

    jFreeChart应用

    **jFreeChart应用详解** jFreeChart是一款强大的Java图表库,它允许开发者在Java应用程序、Swing组件、Web应用程序以及服务器端生成各种高质量的图表,包括柱状图、饼图、线形图、散点图、甘特图等。这款开源库在...

    struts2+MySQL+jfreechart生成带热点

    在"struts2+MySQL+jfreechart生成带热点"的场景中,我们可以构建一个Web应用,该应用能够从MySQL数据库中检索数据,然后使用JFreeChart生成包含热点的图表。热点是指图表上的区域,当用户点击这些区域时,可以触发...

    JFreeChart在JSP开发中的应用心得.pdf

    ### JFreeChart在JSP开发中的应用心得 #### 一、引言 随着Web技术的飞速发展,基于互联网的应用程序不再局限于简单的静态内容展示,而是越来越多地涉及到复杂的数据交互和动态内容呈现。传统的应用程序,如报表...

    jfreechart-1.5.2.jar,jfreechart|jfreechart

    jfreechart-1.5.2.jar,jfreechart|jfreechart

    JFreeChart的应用

    本篇将深入探讨JFreeChart的应用,通过实例来展示如何利用这个库来生成各种类型的图表。 ### 一、JFreeChart简介 JFreeChart库提供了丰富的图表类型,如折线图、柱状图、饼图、散点图、甘特图、热力图等,适用于...

    JFreeChart JSP应用例子

    JFreeChart 是一个强大的Java图表库,它提供了丰富的图表类型,包括柱状图、饼图、线图、散点图等,用于在Java应用程序、Swing组件以及Web应用如JSP中展示数据。在"JFreeChart JSP应用例子"中,我们将深入探讨如何在...

Global site tag (gtag.js) - Google Analytics