摘要
本文首先介紹了矢量圖形在移動領域中具有的優勢,然後對其相關技術,包括Mobile SVG、J2ME以及JSR-226和JSR-172進行簡單的介紹。最後,在以上技術的支持下,創建一個簡單基於J2ME的SVGT網絡監控應用。
矢量圖形在移動應用上的優勢
矢量圖形與光柵格式圖像相比,在對動畫、地圖和互動圖形進行編碼和顯示方面的優勢是明顯的。矢量圖形是動態的、可以縮放的,能夠描述非常高級的圖形特性,如復雜形狀、動畫、分層圖形和特殊效果等。
利用矢量圖形的縮放性,圖形可以調整大小,以適應任何顯示設備而不會導致品質損失。這在移動設備上是一個優勢,因為移動設備的顯示屏的形狀、尺寸和分辨率差別很大。矢量圖形還可以很方便的進行平移、縮放、旋轉以及與用戶交互的操作,因此用戶可以在不影響圖形質量的情況下對圖形進行放大,這在使用手機的小屏幕看圖時特別有用。
矢量圖形文件通常小於光柵圖像文件,從而可以縮短無線下載時間,這點對於非常計較帶寬的移動應用來說尤其重要。另外,將當前屏幕上的圖形放大時,對於光柵圖像會出現使圖像模糊的馬賽克效應,此時若要獲得高質量的放大圖像,則需重新從服務器獲取放大後的圖像,從而增加了網絡的流量,而矢量圖形在客戶端進行放大就可以得到沒有質量損失的放大圖形。
矢量圖形的另一個強大功能是可以存儲圖形中各元素的相關信息。例如,通過對建築矢量圖形的附加數據,就可以知道房間的面積,售價等信息。
最後,矢量圖形可以方便的利用搜索引擎對圖形中的屬性進行搜索,實現基於圖形的數據搜索。
目前在移動領域的矢量應用主要包括FlashLite和Mobile SVG等,本文主要討論Mobile SVG。
Mobile SVG標准
SVG(Scalable Vector Graphics,可縮放矢量圖像)是互聯網聯盟(W3C)的正式推薦標准,它是一種使用XML來描述二維圖像的語言。由於SVG的大部分特性非常適合於無線領域的圖形應用,為了滿足移動業界的需求, W3C的SVG工作小組制訂了適合於移動應用領域的Mobile SVG標准。
Mobile SVG主要用於各種資源非常有限的移動設備,所以在實現Mobile SVG時,性能指標成為最主要的指標。由於移動設備在CPU速度、內存大小、支持的顯示顏色等各個參數上有很大的不同,單一的專業標准很難滿足所有移動設備的要求。因此,為了覆蓋不同移動設備家族的需求,SVG工作小組最終制訂了兩個級別的Mobile SVG專業標准。一種專業標准是SVG Tiny (SVGT),適用於資源高度受限的移動設備,如手機;另一種專業標准是SVG Basic (SVGB),適用於高端的移動設備,如PDA等。由於移動設備硬件條件的限制,相對於標准的SVG,Mobile SVG在支持的內容、屬性、功能等方面作了限制。SVGB是標准SVG的子集,而SVGT又是SVGB的子集,SVGT標准中刪除了透明、漸變、裁剪、圖案、符號和蒙板等復雜功能,而且沒有對腳本支持。具體的不同請參考W3C SVG網址。
以下是一個SVGT的例子:
<?XML version="1.0" encoding="utf-8"?>
<svg XMLns="http://www.w3.org/2000/svg"
XMLns:xlink="http://www.w3.org/1999/xlink"
XMLns:demo="http://www.sun.com/svg/demo"
id="root"
width="100%" height="100%" vIEwBox="0 0 240 320"
XML:space="preserve"
preserveASPectRatio="none">
<rect fill="#35556B" width="240" height="320"/>
<g id="processingIndicator" transform="translate(120, 97) scale(0.5)" >
<g id="processingIndicator.outerCircle">
<path transform="translate(-120, -97)" fill="#C1CBD1" d="M73.426,97.169c0,25.681,20.894,46.575,46.575,46.575c25.681,0,46.574-20.894,46.574-46.575c0-9.251-2.708-18.192-7.83-25.854c-1.688-2.525-5.104-3.204-7.629-1.516s-3.204,5.104-1.516,7.629c3.908,5.847,5.975,12.673,5.975,19.741c0,19.616-15.959,35.575-35.574,35.575c-19.616,0-35.575-15.958-35.575-35.575c0-19.616,15.959-35.575,35.575-35.575c6.063,0,12.048,1.551,17.307,4.485c2.652,1.48,6.002,0.53,7.482-2.123c1.48-2.653,0.529-6.003-2.123-7.483c-6.893-3.846-14.73-5.879-22.666-5.879C94.319,50.594,73.426,71.488,73.426,97.169z"/>
</g>
<g id="processingIndicator.innerCircle">
<path transform="translate(-120, -97)" fill="#738999" d="M120.001,69.772c-5.441,0-10.701,1.592-15.21,4.607c-2.525,1.688-3.204,5.104-1.516,7.629c1.688,2.525,5.104,3.204,7.629,1.516c2.693-1.8,5.838-2.752,9.096-2.751c4.38,0,8.498,1.705,11.594,4.802c3.098,3.097,4.803,7.214,4.803,11.594c0,9.042-7.355,16.397-16.397,16.397c-9.041,0-16.396-7.355-16.396-16.397l0.065-1.479c0.134-3.034-2.201-5.848-5.236-5.981c-3.034-0.134-5.587,1.972-5.721,5.007l-0.108,2.454c0,15.107,12.29,27.397,27.396,27.397c15.107,0,27.397-12.291,27.397-27.397c0-7.318-2.85-14.198-8.024-19.373S127.318,69.772,120.001,69.772z"/>
</g>
<g id="processingIndicator.center" >
<circle fill="white" transform="translate(-120, -97)" cx="120" cy="97.169" r="9.349"/>
<circle display="none" fill="#35556B" transform="translate(-120, -97)" cx="122.321" cy="92.551" r="2.078"/>
</g>
</g>
<defs>
<animateTransform id="processingIndicatorAnim" xlink:href="#processingIndicator.innerCircle" attributeName="transform" type="rotate" values="0;360" begin="0s" dur="3s" repeatDur="indefinite"/>
<animateTransform xlink:href="#processingIndicator.outerCircle" attributeName="transform" type="rotate" values="0;-360" begin="0s" dur="2s" repeatDur="indefinite"/>
<animateTransform xlink:href="#processingIndicator.center" attributeName="transform" type="rotate" values="0;-360" begin="0s" dur="1s" repeatDur="indefinite"/>
</defs>
<g id="loadProgressBar">
<rect id="loadProgressBar.bkg" fill="#A3B8CB" x="45" y="250" width="150" height="10" />
<rect id="loadProgressBar.progress" fill="white" x="45" y="250" width="20" height="10" />
<text transform="translate(120,230)" fill="#BDBEC0" font-size="12" text-anchor="middle">loading application</text>
<text id="loadProgressBar.text" text-anchor="middle" transform="translate(120,275)" fill="#FFFFFF" font-size="12">0%</text>
</g>
</svg>
Mobile SVG最近已被3GPP組織所采納,用於多媒體短信服務(MMS)。Mobile SVG將很快應用在許多2.5G和3G MMS服務中。Mobile SVG的增強MMS短信功能對於手機制造商具有明顯的吸引力。與運營商一樣,OEM廠商也可以在不對設計作重大變動或不顯著增加成本的情況下,增加 Mobile SVG功能。由於Mobile SVG是內容豐富的通用平台,最適合於幫助設備制造商提供差別化服務。
為了實現SVGT在手機上的應用,開發人員需要了解手機開發平台及其對SVGT的支持情況,其中最常見的是基於Java語言的J2ME移動開發平台。
J2ME應用及其規范擴展
隨著移動技術的發展,手機已經從最初的一種單純的通信工具轉變成如今集通信、工作、娛樂等功能為一體的綜合設備。因此,在移動終端上開發通用的、豐富的應用已成為必然的趨勢。這些應用能夠提供與桌面應用相媲美的功能,並可以按用戶的意願隨時安裝和刪除。然而手機平台在硬件,操作系統等系統底層有很大的不同,給應用程序的開發帶來了很大的困難,開發人員迫切需要一種通用的開發平台。
J2ME(JAVA2 Micro Edition)正是這樣一種JAVA應用開發平台。實際上,JAVA語言從其誕生起就以其運行的平台無關性這一強大的優勢而成為網絡應用的寵兒。J2ME是Java2標准版本的微型版本,專門為小型移動設備所設計。這些設備處理器的處理能力都不強,可使用的資源也有限。因此,J2ME只包含了J2SE中在移動通信設備上所必需的功能和組件,使其能夠在移動設備及其有限的資源上開發出豐富多彩且平台無關的應用。J2ME在結構上分為CDC(Connected Device Configuration)和相應的Foundation Profile規范,以及CLDC(Connected Limited Device Configuration)和相應的MIDP規范。
MIDP(Mobile Information Device Profile)是移動信息設備規范的簡稱,規范具體定義了J2ME適用的硬件和軟件框架,並提供了這個框架要實現的基本功能及其標准接口,應用開發者可以基於這個框架開發出各種應用。2000年9月,SUN公司發布了MIDP的第一個正式版本MIDP1.0。它將J2ME適用的設備定位在至少擁有數百KB RAM和ROM,並具有基本網絡和顯示功能的移動通信設備上。在該基礎上定義了一系列軟件接口,其中包括基本輸入輸出、圖形化用戶接口(GUI)、網絡、事件機制、文件系統、應用管理系統(AMS)等。之後,隨著JAVA技術的不斷發展和用戶需求的不斷提高,SUN公司又於2002年11月發布了MIDP2.0。它對設備的內存資源和處理能力的要求較1.0要高,但也為應用開發者提供了更方便、更豐富多彩的軟件包。MIDP2.0中主要增加了游戲接口的實現、聲音輸出接口的實現安全網絡機制的實現。MIDP2.0的這些特性將使基於移動設備的Java應用具有更加廣闊的前景,也必將使新一代的移動設備發生革命性的變化並領導時尚潮流。
另外,為了支持不同的應用方向,SUN還聯合其它一些公司共同制定了J2ME擴展技術規范,包括圖形應用、網絡服務、多媒體和安全等。其中本文中主要使用到移動2D SVG圖形方面的JSR-226和WEB服務方面的JSR-172。
所有MIDP應用從MIDlet類中派生,MIDlet類管理和控制著應用程序的生命周期,包括裝載、激活、暫停和銷毀四個階段。當設備裝入MIDlet並調用其構造函數時為裝載期,直到程序管理器調用應用程序的startApp()方法。在startApp()調用後,應用程序處於激活期,直到調用了pauseApp() 或 destroyApp() 。pauseApp() 暫停應用程序,而destroyApp()銷毀應用程序。一個典型的MIDlet代碼如下:
import Javax.microedition.midlet.*;
import Javax.microedition.lcdui.*;
public class Hello extends MIDlet
{
private Display display;
public Hello()
{
display = Display.getDisplay(this);
}
public void startApp()
{
Form f = new Form("Test");
f.append("hello world!");
display.setCurrent(f);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
摘要
本文首先介紹了矢量圖形在移動領域中具有的優勢,然後對其相關技術,包括Mobile SVG、J2ME以及JSR-226和JSR-172進行簡單的介紹。最後,在以上技術的支持下,創建一個簡單基於J2ME的SVGT網絡監控應用。
矢量圖形在移動應用上的優勢
矢量圖形與光柵格式圖像相比,在對動畫、地圖和互動圖形進行編碼和顯示方面的優勢是明顯的。矢量圖形是動態的、可以縮放的,能夠描述非常高級的圖形特性,如復雜形狀、動畫、分層圖形和特殊效果等。
利用矢量圖形的縮放性,圖形可以調整大小,以適應任何顯示設備而不會導致品質損失。這在移動設備上是一個優勢,因為移動設備的顯示屏的形狀、尺寸和分辨率差別很大。矢量圖形還可以很方便的進行平移、縮放、旋轉以及與用戶交互的操作,因此用戶可以在不影響圖形質量的情況下對圖形進行放大,這在使用手機的小屏幕看圖時特別有用。
矢量圖形文件通常小於光柵圖像文件,從而可以縮短無線下載時間,這點對於非常計較帶寬的移動應用來說尤其重要。另外,將當前屏幕上的圖形放大時,對於光柵圖像會出現使圖像模糊的馬賽克效應,此時若要獲得高質量的放大圖像,則需重新從服務器獲取放大後的圖像,從而增加了網絡的流量,而矢量圖形在客戶端進行放大就可以得到沒有質量損失的放大圖形。
矢量圖形的另一個強大功能是可以存儲圖形中各元素的相關信息。例如,通過對建築矢量圖形的附加數據,就可以知道房間的面積,售價等信息。
最後,矢量圖形可以方便的利用搜索引擎對圖形中的屬性進行搜索,實現基於圖形的數據搜索。
目前在移動領域的矢量應用主要包括FlashLite和Mobile SVG等,本文主要討論Mobile SVG。
Mobile SVG標准
SVG(Scalable Vector Graphics,可縮放矢量圖像)是互聯網聯盟(W3C)的正式推薦標准,它是一種使用XML來描述二維圖像的語言。由於SVG的大部分特性非常適合於無線領域的圖形應用,為了滿足移動業界的需求, W3C的SVG工作小組制訂了適合於移動應用領域的Mobile SVG標准。
Mobile SVG主要用於各種資源非常有限的移動設備,所以在實現Mobile SVG時,性能指標成為最主要的指標。由於移動設備在CPU速度、內存大小、支持的顯示顏色等各個參數上有很大的不同,單一的專業標准很難滿足所有移動設備的要求。因此,為了覆蓋不同移動設備家族的需求,SVG工作小組最終制訂了兩個級別的Mobile SVG專業標准。一種專業標准是SVG Tiny (SVGT),適用於資源高度受限的移動設備,如手機;另一種專業標准是SVG Basic (SVGB),適用於高端的移動設備,如PDA等。由於移動設備硬件條件的限制,相對於標准的SVG,Mobile SVG在支持的內容、屬性、功能等方面作了限制。SVGB是標准SVG的子集,而SVGT又是SVGB的子集,SVGT標准中刪除了透明、漸變、裁剪、圖案、符號和蒙板等復雜功能,而且沒有對腳本支持。具體的不同請參考W3C SVG網址。
以下是一個SVGT的例子:
<?XML version="1.0" encoding="utf-8"?>
<svg XMLns="http://www.w3.org/2000/svg"
XMLns:xlink="http://www.w3.org/1999/xlink"
XMLns:demo="http://www.sun.com/svg/demo"
id="root"
width="100%" height="100%" vIEwBox="0 0 240 320"
XML:space="preserve"
preserveASPectRatio="none">
<rect fill="#35556B" width="240" height="320"/>
<g id="processingIndicator" transform="translate(120, 97) scale(0.5)" >
<g id="processingIndicator.outerCircle">
<path transform="translate(-120, -97)" fill="#C1CBD1" d="M73.426,97.169c0,25.681,20.894,46.575,46.575,46.575c25.681,0,46.574-20.894,46.574-46.575c0-9.251-2.708-18.192-7.83-25.854c-1.688-2.525-5.104-3.204-7.629-1.516s-3.204,5.104-1.516,7.629c3.908,5.847,5.975,12.673,5.975,19.741c0,19.616-15.959,35.575-35.574,35.575c-19.616,0-35.575-15.958-35.575-35.575c0-19.616,15.959-35.575,35.575-35.575c6.063,0,12.048,1.551,17.307,4.485c2.652,1.48,6.002,0.53,7.482-2.123c1.48-2.653,0.529-6.003-2.123-7.483c-6.893-3.846-14.73-5.879-22.666-5.879C94.319,50.594,73.426,71.488,73.426,97.169z"/>
</g>
<g id="processingIndicator.innerCircle">
<path transform="translate(-120, -97)" fill="#738999" d="M120.001,69.772c-5.441,0-10.701,1.592-15.21,4.607c-2.525,1.688-3.204,5.104-1.516,7.629c1.688,2.525,5.104,3.204,7.629,1.516c2.693-1.8,5.838-2.752,9.096-2.751c4.38,0,8.498,1.705,11.594,4.802c3.098,3.097,4.803,7.214,4.803,11.594c0,9.042-7.355,16.397-16.397,16.397c-9.041,0-16.396-7.355-16.396-16.397l0.065-1.479c0.134-3.034-2.201-5.848-5.236-5.981c-3.034-0.134-5.587,1.972-5.721,5.007l-0.108,2.454c0,15.107,12.29,27.397,27.396,27.397c15.107,0,27.397-12.291,27.397-27.397c0-7.318-2.85-14.198-8.024-19.373S127.318,69.772,120.001,69.772z"/>
</g>
<g id="processingIndicator.center" >
<circle fill="white" transform="translate(-120, -97)" cx="120" cy="97.169" r="9.349"/>
<circle display="none" fill="#35556B" transform="translate(-120, -97)" cx="122.321" cy="92.551" r="2.078"/>
</g>
</g>
<defs>
<animateTransform id="processingIndicatorAnim" xlink:href="#processingIndicator.innerCircle" attributeName="transform" type="rotate" values="0;360" begin="0s" dur="3s" repeatDur="indefinite"/>
<animateTransform xlink:href="#processingIndicator.outerCircle" attributeName="transform" type="rotate" values="0;-360" begin="0s" dur="2s" repeatDur="indefinite"/>
<animateTransform xlink:href="#processingIndicator.center" attributeName="transform" type="rotate" values="0;-360" begin="0s" dur="1s" repeatDur="indefinite"/>
</defs>
<g id="loadProgressBar">
<rect id="loadProgressBar.bkg" fill="#A3B8CB" x="45" y="250" width="150" height="10" />
<rect id="loadProgressBar.progress" fill="white" x="45" y="250" width="20" height="10" />
<text transform="translate(120,230)" fill="#BDBEC0" font-size="12" text-anchor="middle">loading application</text>
<text id="loadProgressBar.text" text-anchor="middle" transform="translate(120,275)" fill="#FFFFFF" font-size="12">0%</text>
</g>
</svg>
Mobile SVG最近已被3GPP組織所采納,用於多媒體短信服務(MMS)。Mobile SVG將很快應用在許多2.5G和3G MMS服務中。Mobile SVG的增強MMS短信功能對於手機制造商具有明顯的吸引力。與運營商一樣,OEM廠商也可以在不對設計作重大變動或不顯著增加成本的情況下,增加 Mobile SVG功能。由於Mobile SVG是內容豐富的通用平台,最適合於幫助設備制造商提供差別化服務。
為了實現SVGT在手機上的應用,開發人員需要了解手機開發平台及其對SVGT的支持情況,其中最常見的是基於Java語言的J2ME移動開發平台。
J2ME應用及其規范擴展
隨著移動技術的發展,手機已經從最初的一種單純的通信工具轉變成如今集通信、工作、娛樂等功能為一體的綜合設備。因此,在移動終端上開發通用的、豐富的應用已成為必然的趨勢。這些應用能夠提供與桌面應用相媲美的功能,並可以按用戶的意願隨時安裝和刪除。然而手機平台在硬件,操作系統等系統底層有很大的不同,給應用程序的開發帶來了很大的困難,開發人員迫切需要一種通用的開發平台。
J2ME(JAVA2 Micro Edition)正是這樣一種JAVA應用開發平台。實際上,JAVA語言從其誕生起就以其運行的平台無關性這一強大的優勢而成為網絡應用的寵兒。J2ME是Java2標准版本的微型版本,專門為小型移動設備所設計。這些設備處理器的處理能力都不強,可使用的資源也有限。因此,J2ME只包含了J2SE中在移動通信設備上所必需的功能和組件,使其能夠在移動設備及其有限的資源上開發出豐富多彩且平台無關的應用。J2ME在結構上分為CDC(Connected Device Configuration)和相應的Foundation Profile規范,以及CLDC(Connected Limited Device Configuration)和相應的MIDP規范。
MIDP(Mobile Information Device Profile)是移動信息設備規范的簡稱,規范具體定義了J2ME適用的硬件和軟件框架,並提供了這個框架要實現的基本功能及其標准接口,應用開發者可以基於這個框架開發出各種應用。2000年9月,SUN公司發布了MIDP的第一個正式版本MIDP1.0。它將J2ME適用的設備定位在至少擁有數百KB RAM和ROM,並具有基本網絡和顯示功能的移動通信設備上。在該基礎上定義了一系列軟件接口,其中包括基本輸入輸出、圖形化用戶接口(GUI)、網絡、事件機制、文件系統、應用管理系統(AMS)等。之後,隨著JAVA技術的不斷發展和用戶需求的不斷提高,SUN公司又於2002年11月發布了MIDP2.0。它對設備的內存資源和處理能力的要求較1.0要高,但也為應用開發者提供了更方便、更豐富多彩的軟件包。MIDP2.0中主要增加了游戲接口的實現、聲音輸出接口的實現安全網絡機制的實現。MIDP2.0的這些特性將使基於移動設備的Java應用具有更加廣闊的前景,也必將使新一代的移動設備發生革命性的變化並領導時尚潮流。
另外,為了支持不同的應用方向,SUN還聯合其它一些公司共同制定了J2ME擴展技術規范,包括圖形應用、網絡服務、多媒體和安全等。其中本文中主要使用到移動2D SVG圖形方面的JSR-226和WEB服務方面的JSR-172。
所有MIDP應用從MIDlet類中派生,MIDlet類管理和控制著應用程序的生命周期,包括裝載、激活、暫停和銷毀四個階段。當設備裝入MIDlet並調用其構造函數時為裝載期,直到程序管理器調用應用程序的startApp()方法。在startApp()調用後,應用程序處於激活期,直到調用了pauseApp() 或 destroyApp() 。pauseApp() 暫停應用程序,而destroyApp()銷毀應用程序。一個典型的MIDlet代碼如下:
import Javax.microedition.midlet.*;
import Javax.microedition.lcdui.*;
public class Hello extends MIDlet
{
private Display display;
public Hello()
{
display = Display.getDisplay(this);
}
public void startApp()
{
Form f = new Form("Test");
f.append("hello world!");
display.setCurrent(f);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
JSR-226技術規范和應用
JSR-226的定義了SVG圖形(Mobile 2D Graphics,M2G)API。其中SVG矢量圖形是ScalableImage的實例,你可以通過靜態的createImage()方法獲得它們。SVGImage是ScalableImage的一個子類,它提供事件處理和底層DOM文檔訪問之間的聯系。大多數情況下我們會使用這個類。例如如何從一個SVGT文件中創建一個SVGImage實例:
try{
InputStream imageStream = getClass().getResourceAsStream("/loadScreen.svg");
SVGImage svgImage = (SVGImage)SVGImage.createImage(imageStream, null);
} catch(Exception e) {
e.printStackTrace();
}
然後,創建ScalableGraphics的一個實例:
ScalableGraphics sg = ScalableGraphics.createInstance();
最後,在paint事件中顯示SVG圖形:
public void paint(Graphics g) {
// *** clear the display
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
// *** render the SVG image
sg.bindTarget(g);
sg.setTransparency(1f);
svgImage.setVIEwportWidth(getWidth());
svgImage.setVIEwportHeight(getHeight());
sg.render(0, 0, svgImage);
sg.releaseTarget();
}
為了使渲染動畫SVG內容的普通情況更加方便,JSR-226還提供了SVGAnimator類。通過SVGAnimator可以創建和控制一個Canvas對象,這個對象自動處理屏幕更新,以播放動畫事件和相應用戶的操作。因此使用SVGAnimator不需要顯式創建ScalableGraphics對象。例如:
try{
InputStream imageStream = SVGMobile.class.getResourceAsStream("/Halloween.svg");
svgImage = (SVGImage)SVGImage.createImage(imageStream, null);
svgAnimator = SVGAnimator.createAnimator(svgImage);
}
catch(Exception e) {
e.printStackTrace();
}
// Set to 10 fps (frames per second)
svgAnimator.setTimeIncrement(0.01f);
svgCanvas = (Canvas)svgAnimator.getTargetComponent();
svgImage.setVIEwportWidth(svgCanvas.getWidth());
svgImage.setVIEwportHeight(svgCanvas.getHeight());
// The SVG root element is used to reset the time on a stop Operation.
doc = svgImage.getDocument();
svg = (SVGSVGElement)doc.getDocumentElement();
svgCanvas.setCommandListener(this);
// Hook-in key listeners to play, pause and stop the animation.
svgAnimator.setSVGEventListener(this);
svgAnimator.play();
state = STATE_PLAYING;
System.err.println("PLAYING...");
// *** grab a reference to the display
display = Display.getDisplay(this);
display.setCurrent(svgCanvas);
// *** set up the midlet menu
int hotKey = 0;
svgCanvas.addCommand(exitCommand);
在應用程序中,不僅可以從SVG文檔裝載靜態的SVG數據,而且可以創建空的SVGImage,然後通過操作其DOM數據形成需要的圖形,下例中創建了一個空SVGImage,然後在DOM樹中追加了一個SVG text元素。
import Javax.microedition.midlet.*;
import Javax.microedition.lcdui.*;
import Javax.microedition.m2g.ScalableGraphics;
import Javax.microedition.m2g.SVGImage;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGElement;
import org.w3c.dom.svg.SVGSVGElement;
import org.w3c.dom.svg.SVGRGBColor;
public class HelloSVG extends MIDlet {
protected SVGImageCanvas svgCanvas = null;
public HelloSVG() {
}
public void startApp() {
SVGImage svgImage = SVGImage.createEmptyImage(null);
Document doc = svgImage.getDocument();
SVGSVGElement svg = (SVGSVGElement) doc.getDocumentElement();
SVGElement textElement = (SVGElement) doc.createElementNS("http://www.w3.org/2000/svg", "text");
textElement.setTrait("#text", "Hello JSR-226 !");
textElement.setFloatTrait("x", 50.0f);
textElement.setFloatTrait("y", 50.0f);
SVGRGBColor textColor = svg.createSVGRGBColor(0, 0, 0);
textElement.setRGBColorTrait( "stroke", textColor);
svg.appendChild(textElement);
svgCanvas = new SVGImageCanvas(svgImage);
Display.getDisplay(this).setCurrent(svgCanvas);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
class SVGImageCanvas extends Canvas {
protected SVGImage svgImage;
protected ScalableGraphics sg = ScalableGraphics.createInstance();
protected SVGImageCanvas(final SVGImage svgImage) {
this.svgImage = svgImage;
}
public void paint(Graphics g) {
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
sg.bindTarget(g);
svgImage.setVIEwportWidth(getWidth());
svgImage.setVIEwportHeight(getHeight());
sg.render(0, 0, svgImage);
sg.releaseTarget();
}
}
這些類都定義在Javax.miroedition.m2g和org.w3c.dom.svg包中,更多內容請參考JSR-226的技術規范文檔。SVG DOM是在org.w3c.dom和org.w3c.dom.events包中定義的。