首页 > 代码库 > highcharts结合JSON实现柱状图
highcharts结合JSON实现柱状图
highcharts是基于javascript的图表库,可以很简单快捷的在web应用程序中添加交互性很强的图表,可以免费提供给个人,非商业用途使用,支持的图表类型有曲线图、区域图、柱状图、饼状图、散状点图和综合图表。
highcharts图表的界面美观,因为是通过javascript编写的,所以不需要安装插件即可运行,且运行的速度极快,兼容性好。本人亲测在IE8(需要将IE8的浏览器模式设置成IE8(B),文本模式设置为IE8标准),firefox33.0,Chrome28.0下图表显示良好,图表导出PNG,JPEG,PDF,SVG位图功能完全正常。附上在IE8上显示的图表截图一张。
以上图表的显示请参照http://www.stepday.com/topic/?951上的示例。如果要实现图表导出png或者jpeg等的功能的话,页面除了引用highcharts的核心js文件highcharts.js之外,还需要引用modules/exporting.js,除此之外,还需要修改下exporting.js,如果要鼠标悬浮出现中文的提示,将printChart ,downloadPNG ,downloadJPEG ,downloadPDF ,downloadSVG,contextButtonTitle 换成中文提示即可,如下所示:
printChart : "打印图表",downloadPNG : "导出 PNG 图像",
downloadJPEG : "导出 JPEG 图像",downloadPDF : "导出 PDF 文档",
downloadSVG : "Download SVG vector image",contextButtonTitle : "图表导出"
还需要将enctype : "multipart/form-data"这行代码注释或者去掉,如果不将这行代码注释或者去掉的话,通过servlet或者action是无法通过提取svg的xml,通过fop将图表转为jpeg格式的图片的。原因在于highcharts的exporting.js中采用的form是mulipart/form类型,使servlet或者action通过request的request.getParemeter获取到的svg的xml字符串为空(具体可以通过控制台输出查看),因此无法输出jpeg格式的图片。我们要输出图片,pdf,SVG位图还需要用到batik-all-1.6.jar(此jar包中集成了很多开源的jar包核心的处理jar包为batik-codec.jar,它是apache项目组下面的一个专门用来处理图形生成技术的开源产品:
The Apache XML Graphics Project currently consists of the following sub-projects, each focused on a different aspect of XML Graphics:
Apache Batik - A toolkit for Scalable Vector Graphics (SVG), based in Java
Apache FOP - A print formatter & renderer for XSL-FO (FO=formatting objects), based in Java
Apache XML Graphics Commons - A library with various components used by Apache Batik and Apache FOP, written in Java
具体是啥意思就有劳各位大神自己去翻译了,所以java通过xml(json)等格式的数据转换为可以收缩大小的矢量图片的功能,当然,其中也有不少依赖的jar包,打开batik-all-1.6.jar我们就可以看到,如下),fop.jar,xerces.jar,这些jar包的来源请自己百度(谷歌被墙了,百度就凑合着用吧),当然我尽量在附件中上传这些jar包,highcharts-3.0.1的的js文件请自行下载,现在需要用到的js文件修改完成,jar包也齐全了。现在来看具体的jsp页面代码(此代参照别人的代码,自己手动加入了下载的功能)。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="http://www.mamicode.com/"> <title>My JSP ‘index.jsp‘ starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <script type="text/javascript" src=http://www.mamicode.com/‘#/‘" /jquery-1.8.0.min.js"></script> <script type="text/javascript" src=http://www.mamicode.com/‘#/‘" /highcharts.js"></script> <script type="text/javascript" src=http://www.mamicode.com/‘#/‘" /modules/exporting.js"></script> <script type="text/javascript" src=http://www.mamicode.com/‘#/‘" /chart.js"></script> <script type="text/javascript" charset="UTF-8"> $(function () { $(‘#container‘).highcharts({ chart: { type: ‘column‘ }, title: { text: ‘数据点线性颜色渐变效果‘ }, xAxis: { categories: [ ‘Jan‘, ‘Feb‘, ‘Mar‘, ‘Apr‘, ‘May‘, ‘Jun‘, ‘Jul‘, ‘Aug‘, ‘Sep‘, ‘Oct‘, ‘Nov‘, ‘Dec‘ ] }, yAxis: { min: 0, title: { text: ‘雨量值 (mm)‘ } }, tooltip: { headerFormat: ‘<span style="font-size:10px">{point.key}</span><table>‘, pointFormat: ‘<tr><td style="color:{series.color};padding:0">{series.name}: </td>‘ + ‘<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>‘, footerFormat: ‘</table>‘, shared: true, useHTML: true }, plotOptions: { column: { pointPadding: 0.2, borderWidth: 0, dataLabels:{ enabled:true, //是否显示数据标签 } } }, credits: { //去掉右下角显示的Highcharts.com声明 enabled: false }, exporting : { filename : ‘chart‘, url : ‘http://localhost:8080/chart/saveAsImage‘,//可以修改exporting.js中对应的url,这里的url会让exporting.js中的无效 }, series: [{ name: ‘Tokyo hot‘, data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4] }] }, function (chart) { SetEveryOnePointColor(chart); }); }); </script> </head> <body> <div id="container" style="width: 60%; height: 350px;"></div> </body> </html>
实现颜色渐变的chart.js代码
//定义一个全局颜色数组(浅蓝色,深蓝色,浅绿色,沙棕色,深卡布色,天蓝色,沙***,宝蓝色,马棕色,灰色,闪光绿色,深灰色) var colorArr = [ ‘#7CB5EC‘, ‘#7171C6‘, ‘#90ED7D‘, ‘#F7A35C‘, ‘#BDB76B‘, ‘#87CEEB‘, ‘#E4D354‘, ‘#436EEE‘, ‘#8D4653‘, ‘#8B8B83‘, ‘#00EE00‘, ‘#B0B0B0‘ ]; //设置每一个数据点的颜色值 function SetEveryOnePointColor(chart) { //获得第一个序列的所有数据点 var pointsList = chart.series[0].points; //遍历设置每一个数据点颜色 for (var i = 0; i < pointsList.length; i++) { chart.series[0].points[i].update({ color: { linearGradient: { x1: 0, y1: 0, x2: 1, y2: 0 }, //横向渐变效果 如果将x2和y2值交换将会变成纵向渐变效果 stops: [ [0, Highcharts.Color(colorArr[i]).setOpacity(1).get(‘rgba‘)], [0.5, ‘rgb(255, 255, 230)‘], [1, Highcharts.Color(colorArr[i]).setOpacity(1).get(‘rgba‘)] ] } }); } }
servlet代码
package com.servlet; import java.io.IOException; import java.io.StringReader; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.batik.transcoder.Transcoder; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.JPEGTranscoder; import org.apache.batik.transcoder.image.PNGTranscoder; import org.apache.fop.svg.PDFTranscoder; public class SaveAsImage extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; public SaveAsImage() { super(); } public void destroy() { super.destroy(); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8");// 设置编码 String type = request.getParameter("type"); String svg = request.getParameter("svg"); String filename = request.getParameter("filename"); // String scale = request.getParameter("scale"); filename = filename == null ? "chart" : filename; ServletOutputStream out = response.getOutputStream(); if (null != type && null != svg) { svg = svg.replaceAll(":rect", "rect"); // 定义文件后缀名 String ext = ""; Transcoder t = null; if (type.equals("image/png")) { ext = "png"; t = new PNGTranscoder(); } else if (type.equals("image/jpeg")) { ext = "jpg"; t = new JPEGTranscoder(); } else if (type.equals("image/svg+xml")) { ext = "svg"; } else if (type.equals("application/pdf")) { ext = "pdf"; t = (Transcoder) new PDFTranscoder(); } response.addHeader("Content-Disposition", "attachment; filename=chart." + ext); response.addHeader("Content-Type", type); if (null != t) { TranscoderInput input = new TranscoderInput(new StringReader(svg)); TranscoderOutput output = new TranscoderOutput(out); try { t.transcode(input, output); } catch (TranscoderException e) { out.print("编码流错误."); e.printStackTrace(); } } else if (ext == "svg") { svg = svg.replace("http://www.w3.org/2000/svg", "http://www.w3.org/TR/SVG11/"); out.print(svg); } else { out.print("Invalid type: " + type); } } else { response.addHeader("Content-Type", "text/html"); } out.flush(); out.close(); } public void init() throws ServletException { } }
web.xml配置代码
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>saveAsImage</servlet-name> <servlet-class>com.servlet.SaveAsImage</servlet-class> </servlet> <servlet-mapping> <servlet-name>saveAsImage</servlet-name> <url-pattern>/saveAsImage</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>aa.jsp</welcome-file> </welcome-file-list> </web-app>
图表的显示与下载功能到此就OK了。
现在来进入本文的重点,结合json实现图表的展示。由于本人的项目中用到了struts2,所以实现图表导出为png,jpeg也是采用的action来实现了,将上面的servlet改写为struts2的action来说应该没啥难度,这里就请广大程序猿自己动手一试吧。既然用到了JSON,就需要用到相关的jar包,我这里用的是json-lib-2.1-jdk15.jar(当然,你也可以使用StringBuffer去手动拼接来实现JSON的格式,前提是你不怕麻烦,不嫌繁琐,不怕出错),在action中,只需要简单的几句代码就能将List集合转换成JSON格式的数据,并通过out.print输出到jsp页面,具体代码如下:
HttpServletResponse response = ServletActionContext.getResponse();
PrintWriter out = response.getWriter();
JSONArray json = JSONArray.fromObject(list);
//输出json,去验证json的格式是否正确
//System.out.println(json.toString());
out.print(json.toString());
控制台输出的json数据为:
[{"STLC":"枝江善溪冲 ","MX":2,"Q":1.45,"WPTN":"4","STCD":"00000001","WZ":null,"TM":"2014-01-02","ADMAUTH":"信息管理单位","RVNM":null,"LOCALITY":null,"STNM":"雨量站","Z":1.45}]
当页面访问该action的时候,JSON格式的数据已经输出到jsp页面了。现在我们可以通过jquery的ajax方式访问action,并且在成功的回调函数返回数据,并进行解析,具体代码如下:
//显示higthcharts图表 var chart; var time; var z; var q; function showCharts(){ $.ajax({ type : ‘POST‘, dataType:‘json‘, async: false, url :‘/water/water!getDayList.action‘, data:{ tm:$("#w_d_l_tm").val() }, success:function(data) { //遍历 $.each(data,function(i,t){ stlc=t.STLC.trim(); time=t.TM; z=t.Z; q=t.Q; //初始化highcharts图表 chart = new Highcharts.Chart({ chart : { renderTo : ‘container‘, //制定图标显示的层的id //defaultSeriesType: ‘column‘//柱状图 line直线图,spline折线图,pie饼状图,area区域图,more综合图 type:‘column‘ //zoomType: ‘xy‘, }, credits: { //去掉右下角显示的Highcharts.com声明 enabled: false }, title : { text : stlc+‘水情日报表‘, x : -20 }, //X坐标 xAxis : { categories : [‘水位‘,‘流量‘] }, //Y坐标(分别有水位与流量两个) yAxis : [ { title : {text : ‘水位(m)‘}, style:{color:‘#89A54E‘}, opposite: false }, { gridLineWidth: 0, title: {text: ‘流量(m3/s)‘}, style:{color: ‘#4572A7‘}, opposite: true } ], exporting : { filename : ‘chart‘, url : ‘/chartImage!chart.action‘ }, //此处是关键点,也可以修改exporting.js中对应的url,如果不需要此功能,不写exporting即可 /*如果只需要将图表导出为指定格式的图片请使用下面的方法,即重写exporting中的一些东西 exporting: { type:‘image/png‘, url:‘http://127.0.0.1:8080/yeqh/chartImg/‘, buttons: { contextButton: { menuItems: [, { text: ‘导出PNG图片文件‘, onclick: function() { this.exportChart(); }, separator: false }] } } } */ //鼠标悬浮提示 tooltip : { formatter : function() { return this.x + ‘: ‘ + this.y; } }, //设置图例 /* legend : { layout : ‘vertical‘, //水平排列 //线条说明停靠位置 align : ‘right‘, verticalAlign : ‘middle‘, x : 10, y : 100, shadow: true, //设置阴影 borderWidth : 0, floating: true, }, */ plotOptions:{ column:{ pointPadding: 0.5, borderWidth: 0, pointWidth: 30, //这种柱状的宽度 dataLabels:{ enabled:true, //是否显示数据标签 } } }, series : [ { name : ‘水位‘, data :[z,q] } ] }); }); } }); }
jsp需要定义一个div,此div的id与上面js中的renderTo的属性要相同,
<div id="container" style="width: 80%; height: 400px; margin-left: auto; margin-right: auto;"></div>
到这里,highcharts结合json显示图表已经完成,如果想要实现柱状图渐变的图标效果,请自己加上实现颜色渐变的js代码去实现。需要用的js文件与jar包请到http://down.51cto.com/data/1890578自行下载。
本文出自 “java小菜” 博客,请务必保留此出处http://3440684.blog.51cto.com/3430684/1568764
highcharts结合JSON实现柱状图