為了開始運行本文所給的例子,你需要JDK 1.2或它的更高版本( http://java.sun.com )。你還需要一個支援JSP的Web伺服器。我在Tomcat上測試該例子,我用com.sun.image.codec.jpeg類別(在Sun Java 2 SDK中發布)進行圖形資料的編碼。
既然你希望擁有可重複使用的背景,你應該建立一個Java類別來管理佈局,包括標題區和外部邊界。如圖A所示。
圖A
正如你所看到的那樣,我在標題區和外部邊界上都進行了陰影處理。標題有一個白色的、一個像素寬的邊界,圖形區有一個細的黑色邊界。這些邊界增加了陰影的清晰度。
邊界很容易產生。用Graphics2D物件的fill()方法來填滿一個藍色的標題矩形,然後用draw()方法用其它顏色畫出邊界。
產生陰影效果也很簡單。首先,用fill()方法畫出一個陰影。然後,在偏移七個像素的地方畫出標題。這個偏移產生了三維的效果,這樣就得到了陰影效果。
假設有一家公司銷售農產品,它需要一個直方圖來顯示銷售額。在實際應用場合下,我們需要從一個資料庫或XML檔案中取得這些數據,但是為了簡單起見,我們假設銷售額數據保存在下面的兩個陣列中:
String datanames[] = {"蘋果", "桔子", "桃子", "檸檬", "柚子"};
int datavalues[] = {11, 62, 33, 102, 50};
第一個陣列保存該公司出售的各種農產品的項目。第二個數組為對應各農產品的銷售額。
直方圖將以JPEG格式顯示並儲存,所以我們需要正確設定MIME,也就是內容類型。瀏覽器利用MIME類型決定如何做出反應。下面的程式碼用以設定MIME類型:
response.setContentType("image/jpeg");
接下來,我們需要一個表示該圖像的物件。 Java 2D API支援BufferedImage類,它提供了一種在記憶體中保存和管理像素資料的方法。我們希望圖形是彩色的,所以使用了TYPE_INT_RGB圖形類型。 WIDTH和HEIGHT這兩個整形資料用來以像素為單位指定該影像的寬度和高度:
BufferedImage bi = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
現在我們有個BufferedImage對象,我們可以透過呼叫該物件的createGraphics()方法來設定Graphics2D的內容:
Graphics2D biContext = bi.createGraphics();
創建該圖的程式設計師需要根據該圖形的重要性和頁面的整體佈局來設定WIDTH參數。圖形元素根據圖形寬度的改變自動調整自身的大小。
標題的寬度和邊界區域,以及圖形的最長直方塊需要根據WIDTH參數進行計算。這樣做的目的是為了確保所有的圖形元素都沒有超過圖形的寬度而越過圖形的右邊界。
需要顯示的資料條目數決定了圖形的HEIGHT參數。如果有新的元素添加到datavalues[]和datanames[]數組,那麼圖形的高度就應該對應增長以適應所需顯示的區域大小。
maximum參數用於最長直方塊。然後,其它直方塊的寬度按照相對於maximum的量進行計算:
int barWidth = (innerWIDTH * currentValue) / maximum;
上面的演算法用到了maximum和圖形的innerWIDTH (圖形區域)這兩個數值來確保直方塊會隨著WIDTH數值的改變而自動伸縮。
為了顯示該圖形,我們需要建立一個背景圖像,然後新增圖形資料。首先,建立一個graphBG物件並呼叫它的draw()方法:
graphBG gr = new graphBG();
gr.draw(biContext, WIDTH, HEIGHT, "Farm Produce", "Overall Average: " + average);
draw()方法的參數包括圖形內容、 biContext 、WIDTH和HEIGHT , graphBG類別利用它們來決定標題和圖形區域的寬度和高度。最後,計算average資料值並將其新增至標題中顯示的文字。
每個直方塊的縱座標(y軸)位置依照下列公式計算: y_pos = i * displayHeight + headerOffset 。其中displayHeight等於直方塊上文字的高度加上直方塊的高度, headerOffset表示從圖形頂端開始的垂直距離,包括標題區域以及陰影的高度。
我用了前面創建標題邊界的技術創建了這些直方塊以及它們的邊界。我把直方塊邊界的寬度和高度分別減去一個像素,這樣每個直方塊看起來都有一個紅色的邊界,並通過在白色背景上畫上內邊界使得減切效果的產生變得簡單起來。
我們已經在記憶體中建立了這張圖片,現在我們對它進行編碼並把它顯示給用戶。我們不能用預設得JSP輸出流來處理JPEG,所以我們需要利用response.getOutputStream()從回應物件取得流。我們可以用輸出流來建立一個JPEGImageEncoder物件並呼叫它的encode() ,傳遞我們在前面建立的BufferedImage物件:
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output);
encoder.encode(bi);
產生的圖象相對較小,只佔了13.7千位元組的容量。圖B給出了最終的效果:
圖B
無論從那個方面來說, index.jsp的輸出都是一個JPEG影像。你可以把它保存到你的桌面上或按PrintScreen鍵來抓圖。如果你需要在同一頁上顯示多幅圖形或把圖形引入到其它內容中,你可以使用HTML的img標記(< img src = ”index.jsp”> ),然後,當需要時放置該圖,如利用一個表格。
也許最老的用於動態產生圖形的Internet技術之一可以實現處了顯示一個圖像之外的其它任務。設想你需要記錄這副圖的瀏覽人數(類似記錄廣告點擊次數的情況),那麼你需要在index.jsp中實現諸如點擊計數、資料庫或文件訪問之類的任務,你可以在後台處理這些任務而不需要利用緩衝頁面切換給使用者。
我們在本文之中檢驗了一種產生整齊、看上去很舒服的直方圖。我們巧妙的處理了圖形尺寸的改變以及編碼為JPEG格式,並且討論了透過修改HTML程式碼的方式把最終產生的圖片放置在頁面的不同位置上。