JQuery插件之-Highcharts在****項目中的應用-進階篇
WYQ
本文檔主要講Highcharts的2個地方的改進之處,1是在柱狀圖中爲每個柱子設置不同的顏色,2是改造highchars自帶的圖表下載功能。
1. 在柱狀圖中給每塊柱子設置七彩斑斕的顏色,做完之後,可以在餅狀圖,折線圖等圖表上實現相同的效果:在Highcharts自帶的例子中如column-basic.htm中,相同屬性的柱子只有1種默認的顏色可以設置,在遇到要求同一個柱子使用不同色彩的時候,higcharts的demo和example中沒有給出解決辦法:
如果我們要實現:
這種效果,就需要對數據結構做個特殊處理.
首先了解一下highcharts接收的json數據格式:
charts\[\d+\]\.name,
charts\[\d+\]\.data\[\d+\]
Charts是一個list類型的結構,data是一個數組,數組中的對象可以是map,也可以是int 或者string類型的,它表示了Y軸對應的一些參數屬性。Chartscategories表示圖表中的x軸的對應的名稱;在java中構造出這個數據結構後,生成json數據發給highcharts就可以在頁面上生成圖表了。
前端頁面的代碼如下:
function gethighcharts(obj){
var chart;
var options = {
chart: {
renderTo: 'containerdata',
defaultSeriesType: 'column',
marginRight: 100,
marginBottom: 25
},
title: {
text: '各科成績得分比較',
x: -20 //center
},
subtitle: {
text: '',
x: -20
},
xAxis: {
categories: []
},
yAxis: {
minorTickInterval: 'auto',
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
},
series: []
};
同時在頁面需要引入對應的js庫文件:
<script type="text/javascript" src="js/highcharts/highcharts.js"></script>
<script type="text/javascript" src="js/highcharts/exporting.js"></script>
通過測試時發現,在charts的data結構中,給每個map再加入一個color屬性就可以使得每個柱狀圖有不同的顏色,對應的json數據的格式改爲如下就可以:
對於每個柱狀圖的顏色可以預先在一個java對象中定義好,然後每次循環賦值給柱子就行了,比如我在程序中預先定義好了9種顏色,每次生成data數據時候就循環插入color的值就可以了
String[] colors = {"#4572A7", "#AA4643", "#89A54E", "#80699B", "#3D96AE", "#DB843D", "#92A8CD", "#A47D7C", "#B5CA92"};
2. 改造Highcharts的圖表的下載功能:
在Highcharts中使用自帶的下載功能的時候,它會在下載彈出框中顯示來自於export.higcharts.com字樣,在圖表的右下角也會有顯示HightChart.com的超鏈接字樣,在我們****的項目中,很明顯需要將這兩處地方進行替換,將這兩個地址轉換爲我們自己的域名地址。
於是我們進行嘗試,在該插件的JS庫文件exporting.js文件中將相關字樣轉爲我們自己的域名,在其第8行的位置,我們將導出功能的英文提示改換爲了漢字提示,然後在第10行將highcharts的域名換爲了我們自己的域名:如:
但是經過這樣一改之後,運行程序後,下載功能完全失效,不能再用了。經過仔細分析,發現http://export.highcharts.com/這個地址不僅僅是一個簡單的域名錶示,而且它是一段PHP的超鏈接的URI地址(類似於java中的servlet地址),它的作用是將highcharts圖表所用的參數傳遞給這個URI地址,由該URI來生成指定格式的圖片,然後以IO流的形式返回給用戶下載該圖片,用googlle在highcharts的論壇上查找源代碼,發現了其處理的步驟,於是參照了之前網上牛人的程序用java的servlet仿寫一個對應的處理程序,因爲要完全以參數來生成圖片,所有用到了很多的開源的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包,都是該包的一些依賴包。那有了這些jar包後,我們就可以開發自己的servlet用來生成higcharts的圖表了,代碼如下:
package cn.tools;
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 HeighChartsExportUtil extends HttpServlet{
/**
* highcharts的export功能用到的Java輔助類
* 20100617@wyq
*/
private static final long serialVersionUID = 2144151124530961067L;
public HeighChartsExportUtil() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
doPost(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException{
request.setCharacterEncoding("utf-8");//注意編碼
String type = request.getParameter("type");
String svg = request.getParameter("svg");
response.setCharacterEncoding("utf-8");
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("application/pdf")) {
ext = "pdf";
t = new PDFTranscoder();
} else if (type.equals("image/svg+xml")) {
ext = "svg";
}
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();
}
}
詳細代碼可以參考cn.tools. HeighChartsExportUtil該類,說明一點,其中用到了request.setCharacterEncoding("utf-8");這句代碼,如果去掉該句代碼,那麼在生成的圖表圖片中如果有漢字的話,就會成爲亂碼,所以一定要加這句,之前用highcharts自帶的URI的時候,我們圖標圖片中的漢字亂碼沒法解決,現在通過該servlet就可以解決了。然後在web.xml配置文件中加入該servlet的映射:
<!--highcharts SVG 圖像導出輔助類-->
<servlet>
<servlet-name>HighChartsServlet</servlet-name>
<servlet-class>cn.tools.HeighChartsExportUtil</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HighChartsServlet</servlet-name>
<url-pattern>/getHighchartServlet</url-pattern>
</servlet-mapping>
<!--highcharts SVG 圖像導出輔助類-->
然後現在在exporting.js中放心的將http://export.highcharts.com/改爲我們自己的地址了,我這裏改爲了http://localhost:8080/SchoolManageSystem/getHighchartServlet這個地址:然後就可以在圖表中顯示我們自己的地址了,如下圖所示:
通過這個例子發現:在開發工作中,很小的一個地方的變動,或者頁面上一個很細微效果的改變,都需要我們在後臺做出很多的準備工作才能實現的,或許這就是我們開發工作的特點吧,後臺做的再多,給別人留下印象的,也就是前臺頁面上的那一瞥而已。