HightCharts学习

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();

}

}