zhaolinru 2016-08-25
Highcharts是一个使用javascript脚本来生成图表的工具,和jfreechart作用类似,都用来生成各种图表,并支持图片的导出和打印。
从官网www.highcharts.com上下载的压缩表中的example中有各种图表的例子。
要编写生成图表的例子建议从文件名后带basic的文件看起,看到例子后你会发现,highcharts使用起来时非常简单的,我们要做的仅仅是把数据组织好,让在页面onload时把数据设置到组件(Highcharts.Chart)中即可。
一、改改自带的例子http://export.highcharts.com/
先来个例子:
第一步:下载Highcharts-2.1.3.zip包和jquery-min-1.4.2.js
以下两个文件的下载地址:
http://www.highcharts.com/download
http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js
第二步:创建一个html文件在文件的head标签部分,加入对相关js文件的引入:
<scripttype="text/javascript"src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
Highcharts的核心文件
<scripttype="text/javascript"src="../js/highcharts.js"></script>
处理导出图片功能的js文件
<scripttype="text/javascript"src="../js/modules/exporting.js"></script>
第三步:编写相关js代码
在上面的导入js文件代码后继续加入以下代码:
<!--2.AddtheJavaScripttoinitializethechartondocumentready-->
<scripttype="text/javascript">
varchart;
$(document).ready(function(){
chart=newHighcharts.Chart({
chart:{
renderTo:'container',
defaultSeriesType:'line',
marginRight:130,
marginBottom:25
},
title:{
text:'MonthlyAverageTemperature',
x:-20//center
},
subtitle:{
text:'Source:WorldClimate.com',
x:-20
},
xAxis:{
categories:['Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec']
},
yAxis:{
title:{
text:'Temperature(°C)'
},
plotLines:[{
value:0,
width:1,
color:'#808080'
}]
},
tooltip:{
formatter:function(){
return'<b>'+this.series.name+'</b><br/>'+
this.x+':'+this.y+'°C';
}
},
legend:{
layout:'vertical',
align:'right',
verticalAlign:'top',
x:-10,
y:100,
borderWidth:0
},
series:[{
name:'Tokyo',
data:[7.0,6.9,9.5,14.5,18.2,21.5,25.2,26.5,23.3,18.3,13.9,9.6]
},{
name:'NewYork',
data:[-0.2,0.8,5.7,11.3,17.0,22.0,24.8,24.1,20.1,14.1,8.6,2.5]
},{
name:'Berlin',
data:[-0.9,0.6,3.5,8.4,13.5,17.0,18.6,17.9,14.3,9.0,3.9,1.0]
},{
name:'London',
data:[3.9,4.2,5.7,8.5,11.9,15.2,17.0,16.6,14.2,10.3,6.6,4.8]
}]
});
});
</script>
第四步:准备存放图片的容器
在<body>标签中加入:
<divid="container"style="width:800px;height:400px;margin:0auto"></div>
运行下试试。
这样就完成了一个最基本的曲线图的例子。
接下来的是如果我们要自己实现一个该怎么弄?
很简单,修改例子代码就可以了,用不着自己重新写代码。
1.先对比刚才写的例子的代码和效果,看看那些东西我们可以修改:
很明显,标题的文字、纵轴的单位,横轴的文字,这些都要修改,数据部分先不管。
于是,在html文件中,修改标题为:我的标题
修改代码为:
title:{
text:'我的标题',
x:-20//center
},
保存再打开html,我自己在试验的使用用的是ultraEdit编辑器编辑的html文件,发现文件里面的摄氏度出现乱码,
当时没在意,用firefox查看源文件,把摄氏度这个符号给copy过来了,保存后打开时没出现效果。
然后查看源文件的时候出现乱码,应该是编辑器把文件的编码修改了,所以在改的时候最好用记事本,保存时,保存为utf-8编码的。或者干脆放在我们的开发工具中修改。
改后的效果如下:
接着把子标题、纵轴的单位和鼠标移上图片时提示中的内容也进行修改
subtitle:{//修改子标题
text:'来源:bits.digitalchina.com',
x:-20
},
yAxis:{//修改纵轴单位文字
title:{
text:'温度(摄氏度)'
},
plotLines:[{
value:0,
width:1,
color:'#808080'
}]
},
tooltip:{
formatter:function(){
return'<b>'+
this.series.name+'</b><br/>'+
this.x
+':'+this.y+'摄氏度';
}
},
修改这些东西都很简单,只用在html中找到这些字符,然后替换就可以了。
接下来的是数据了。
我们看一下横轴的数据,这些值都定义在:
xAxis:{
categories:['Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec']
},
我们再想想,这个曲线是怎么画出来的?
无非是X、y轴的值确定一点,多点连成线。
查看代码中表示数据的部分:
series:[{
name:'Tokyo',
data:[7.0,6.9,9.5,14.5,18.2,21.5,25.2,26.5,23.3,18.3,13.9,9.6]
},{
name:'NewYork',
data:[-0.2,0.8,5.7,11.3,17.0,22.0,24.8,24.1,20.1,14.1,8.6,2.5]
},{
name:'Berlin',
data:[-0.9,0.6,3.5,8.4,13.5,17.0,18.6,17.9,14.3,9.0,3.9,1.0]
},{
name:'London',
data:[3.9,4.2,5.7,8.5,11.9,15.2,17.0,16.6,14.2,10.3,6.6,4.8]
}]
上面的series属性是一个数组,该数组中有四个json对象,而图上刚好是四条线,所以应该是一个json对象对应一条线,而且name属性值也说明了这点。
我们现在只要弄懂一条线是怎么来的,就好办了。
拿其中一条来说
{name:'Tokyo',data:[7.0,6.9,9.5,14.5,18.2,21.5,25.2,26.5,23.3,18.3,13.9,9.6]}
表示的是Tokyo的数据,data里面存放的是一维数组,查看tokyo对应的那条线发现
这些值刚好是那些点的纵轴的值。那横轴呢?
横轴刚好是xAxis:{
categories:['Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec']
},
这时你会想到,原来xAxis就是表示点的x轴线值,而xAxis这个数组的长度也肯定和data的长度一样,这样刚好一个确定纵轴,一个确定横轴。
这样就可以表示tokyo这个城市Jan的温度是7.0
Feb的温度是6.9
...........
现在问你,如果只要一条线呢?把series中只保留一个元素即可。如:
series:[{
name:'Tokyo',
data:[7.0,6.9,9.5,14.5,18.2,21.5,25.2,26.5,23.3,18.3,13.9,9.6]
}]
如果只要Jan,Feb,Mar这三个月的温度呢?修改data,只要前三个月的数字,当然还要修改xAxis
series:[{
name:'Tokyo',
data:[7.0,6.9,9.5]
}]
xAxis:{
categories:['Jan','Feb','Mar']
},
现在我想图片上最明显的要修改的部分,都可以改了,我们应该可以使用它了。
二、自己动手写一个jsp,加载从服务端获取的数据。
第一步、在web工程下新建一个jsp,将相关的js文件放到项目中
还是拷贝刚才的javascript和html代码到jsp中
发布项目,打开这个jsp以确保引入的js文件路径没有问题。
第二步、准备服务端代码,我们准备还是用刚才的那个气温的例子,
在服务端拼接好series属性需要的字符串,可以就用servlet完成,
核心代码如下:
doPost(......){
//........
Out.println(
"["+
"{name:'Tokyo',data:[7.0,6.9,9.5,14.5,18.2,21.5,25.2,26.5,23.3,18.3,13.9,9.6]},"+
"{name:'NewYork',data:[-0.2,0.8,5.7,11.3,17.0,22.0,24.8,24.1,20.1,14.1,8.6,2.5]},"+
"{name:'Berlin',data:[-0.9,0.6,3.5,8.4,13.5,17.0,18.6,17.9,14.3,9.0,3.9,1.0]},"+
"{name:'London',data:[3.9,4.2,5.7,8.5,11.9,15.2,17.0,16.6,14.2,10.3,6.6,4.8]}"+
"]"
);
//......
}
Web.xml中的配置:
<servlet>
<servlet-name>pp</servlet-name>
<servlet-class>cn.dc.serverlt.HighChartsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>pp</servlet-name>
<url-pattern>/pp.do</url-pattern>
</servlet-mapping>
第三步、修改jsp:
<scripttype="text/javascript">
$(document).ready(function(){
varoptions={
chart:{
renderTo:'container',
defaultSeriesType:'line',
marginRight:130,
marginBottom:25
},
credits:{
href:'http://bits.digitalchina.com',
text:'bits'
},
title:{
text:'昨日系统访问数量统计图',
x:-20//center
},
subtitle:{
text:'Source:bits',
x:-20
},
xAxis:{
categories:[]
},
yAxis:{
title:{
text:'个/小时'
},
plotLines:[{
value:0,
width:1,
color:'#808080'
}]
},
tooltip:{
formatter:function(){
return'<b>'+this.series.name+'</b><br/>'+
this.x+':'+this.y+'个';
}
},
legend:{
layout:'vertical',
align:'right',
verticalAlign:'top',
x:-10,
y:100,
borderWidth:0
},
exporting:{
filename:"chart",
type:"image/png",
url:'http://localhost:8888/dcweb/pp.do',
width:800
},
series:[]
};
$.get('/infoAdmin/visitorStatistics.do',function(data){
//Createthechart
alert(data);
data=eval("("+data+")");
alert(data);
options.series.push(data);
varchart=newHighcharts.Chart(options);
});
});
</script>
这里我没有先定义chart,而是先定义一个普通的javascript对象options,
然后给其设置一个series的数组属性(值是空的),
然后发送异步请求获取数据,
将响应数据做处理,被设置到options对象的series属性上。
这样options对象实际上有了Highcharts.Chart所需的所有配置属性信息。
我们在用options来构建一个Highcharts.Chart对象。
之所以没有直接先定义Highcharts.Chart是因为,定义之后不能直接在初始化时设置值,而图表是在产生newHighcharts.Chart对象后立即生成的,所以肯定就没有数据了。
到现在,我也不清楚里面的每个参数是做什么的,但是可以查文档,以下是文档的访问地址:http://www.highcharts.com/ref/,文档还不知道怎么下载下来,大家只能先看在线的文档了。
注意看的时候对照例子中的js代码,这样你大概就能知道一些基本参数的作用了。
我们的项目中用的话,应该不会要很复杂的功能,所以能基本应付开发需要。
三、怎么去掉图表右下角的Highcharts.com的标志?
1.最笨的方法:改源码,查找highcharts.com这是我首先想到的。
2.查看api时发现了
credits:{
href:'http://bits.digitalchina.com',
text:'bits'
}
这样就可以随意修改成我们自己的了。
四、图片导出,怎么变成我们自己的呢,而不是每次都请求
Exports.highcharts.com?
本来如果要是没有中文乱码的话,我也不会去找替代方案。
我们点击导出图片的时候实际上是吧svg图片数据以post请求的方式发送给了
Exports.highcharts.com,该站点是以php程序出来这些数据的。
(有兴趣的同志可以用firebug或httpwatch工具查看下发送的请求数据)
现在知道是发svg图片数据发送给服务端去处理的,那么要解决中文乱码就小菜一碟了,
request.setCharacterEncoding("utf-8");
就可以搞定了。
这个是从某位高手那里找来的,老外写的,用java来处理svg图片数据导出各种图片。
使用的是apache的batik,必须下载batik的jar包,
这个包是干嘛的?我现在只知道是用来将svg图片数据转成各种格式图片的。
代码如下
packagecn.dc.serverlt;
importjava.io.IOException;
importjava.io.StringReader;
importjavax.servlet.ServletException;
importjavax.servlet.ServletOutputStream;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.apache.batik.transcoder.Transcoder;
importorg.apache.batik.transcoder.TranscoderException;
importorg.apache.batik.transcoder.TranscoderInput;
importorg.apache.batik.transcoder.TranscoderOutput;
importorg.apache.batik.transcoder.image.JPEGTranscoder;
importorg.apache.batik.transcoder.image.PNGTranscoder;
importorg.apache.fop.svg.PDFTranscoder;
/**
*ServletimplementationclassforthebatikTranscoder
*@Thanksprzemyslaw
*/
publicclassHighChartsServletextendsHttpServlet{
privatestaticfinallongserialVersionUID=3920224595120519682L;
publicHighChartsServlet(){
super();
}
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
doPost(request,response);
}
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
request.setCharacterEncoding("utf-8");
Stringtype=request.getParameter("type");
Stringsvg=request.getParameter("svg");
ServletOutputStreamout=response.getOutputStream();
if(null!=type&&null!=svg){
//ThislineisnecessaryduetoabuginthehighchartsSVGgeneratorforIE
//I'mguessingitwontbeneededlater.
svg=svg.replaceAll(":rect","rect");
Stringext="";
Transcodert=null;
if(type.equals("image/png")){
ext="png";
t=newPNGTranscoder();
}elseif(type.equals("image/jpeg")){
ext="jpg";
t=newJPEGTranscoder();
}elseif(type.equals("application/pdf")){
ext="pdf";
t=newPDFTranscoder();
}elseif(type.equals("image/svg+xml")){
ext="svg";
}
response.addHeader("Content-Disposition","attachment;filename=chart."+ext);
response.addHeader("Content-Type",type);
if(null!=t){
TranscoderInputinput=newTranscoderInput(newStringReader(svg));
TranscoderOutputoutput=newTranscoderOutput(out);
try{
t.transcode(input,output);
}catch(TranscoderExceptione){
out.print("Problemtranscodingstream.Seetheweblogsformoredetails.");
e.printStackTrace();
}
}elseif(ext=="svg"){
out.print(svg);
}else{
out.print("Invalidtype:"+type);
}
}else{
response.addHeader("Content-Type","text/html");
out.println("Usage:\n\tParameter[svg]:TheDOMElementtobeconverted.\n\tParameter[type]:ThedestinationMIMEtypefortheelmenttobetranscoded.");
}
out.flush();
out.close();
}
}