相較於位圖(JPG、PNG),矢量圖形(SVG)在移動裝置具備決定性優勢:
W3C 針對資源受限裝置制定兩個子集:
| 特性 | SVGT (Tiny) | SVGB (Basic) |
|---|---|---|
| 目標裝置 | 手機、極低階 PDA | 高階 PDA、智慧型手機 |
| 支援功能 | 基本形狀、路徑、文字、簡單動畫、無腳本 | SVGT 全部 + 漸層、裁剪、蒙版、腳本子集 |
| 關係 | SVGT ⊂ SVGB ⊂ SVG 1.1 Full | |
SVGT 移除:透明度、漸層、裁剪路徑、圖案、符號、蒙版、腳本。檔案通常以 .svg 或壓縮後的 .svgz 發行。
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="https://www.w3.org/2000/svg"
xmlns:xlink="https://www.w3.org/1999/xlink"
id="root" width="100%" height="100%"
viewBox="0 0 240 320"
preserveAspectRatio="none">
<rect fill="#35556B" width="240" height="320"/>
<g id="processingIndicator" transform="translate(120,97) scale(0.5)">
<g id="processingIndicator.outerCircle">
<path fill="#C1CBD1" d="M73.426,97.169c0,25.681,20.894,46.575,46.575,46.575..."/>
</g>
<g id="processingIndicator.innerCircle">
<path fill="#738999" d="M120.001,69.772c-5.441,0-10.701,1.592..."/>
</g>
<g id="processingIndicator.center">
<circle fill="white" cx="120" cy="97.169" r="9.349"/>
</g>
</g>
<defs>
<animateTransform 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"/>
</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>
SVGImage、ScalableGraphics、SVGAnimator。javax.xml.parsers)。public class Hello extends MIDlet {
private Display display;
public Hello() { display = Display.getDisplay(this); }
protected void startApp() {
Form f = new Form("Test"); f.append("hello world!");
display.setCurrent(f);
}
protected void pauseApp() {}
protected void destroyApp(boolean unconditional) {}
}
四階段:載入 → startApp()(啟動) → pauseApp()(暫停) → destroyApp()(銷毀)。
try {
InputStream is = getClass().getResourceAsStream("/loadScreen.svg");
SVGImage svgImage = (SVGImage) SVGImage.createImage(is, null);
ScalableGraphics sg = ScalableGraphics.createInstance();
// 在 Canvas.paint() 中
public void paint(Graphics g) {
g.setColor(0xFFFFFF); g.fillRect(0,0,getWidth(),getHeight());
sg.bindTarget(g);
sg.setTransparency(1f);
svgImage.setViewportWidth(getWidth());
svgImage.setViewportHeight(getHeight());
sg.render(0, 0, svgImage);
sg.releaseTarget();
}
} catch (Exception e) { e.printStackTrace(); }
try {
InputStream is = getClass().getResourceAsStream("/Halloween.svg");
SVGImage svgImage = (SVGImage) SVGImage.createImage(is, null);
SVGAnimator animator = SVGAnimator.createAnimator(svgImage);
animator.setTimeIncrement(0.01f); // 100 fps 精度
Canvas svgCanvas = (Canvas) animator.getTargetComponent();
svgImage.setViewportWidth(svgCanvas.getWidth());
svgImage.setViewportHeight(svgCanvas.getHeight());
svgCanvas.setCommandListener(this);
animator.setSVGEventListener(this); // 處理動畫事件
animator.play();
Display.getDisplay(this).setCurrent(svgCanvas);
} catch (Exception e) { e.printStackTrace(); }
SVGImage svgImage = SVGImage.createEmptyImage(null);
Document doc = svgImage.getDocument();
SVGSVGElement svg = (SVGSVGElement) doc.getDocumentElement();
SVGElement textEl = (SVGElement) doc.createElementNS("https://www.w3.org/2000/svg", "text");
textEl.setTrait("#text", "Hello JSR-226 !");
textEl.setFloatTrait("x", 50f);
textEl.setFloatTrait("y", 50f);
SVGRGBColor color = svg.createSVGRGBColor(0,0,0);
textEl.setRGBColorTrait("stroke", color);
svg.appendChild(textEl);
// 繪製同上,使用 ScalableGraphics.render()
javax.microedition.m2g:M2G 核心 API(SVGImage, ScalableGraphics, SVGAnimator...)org.w3c.dom.svg:SVG DOM 介面(SVGElement, SVGSVGElement, SVGRGBColor...)org.w3c.dom、org.w3c.dom.events:標準 DOM 事件模型