SVG腳本編程介紹(二)
人氣:13721
三、 腳本編程應用實例
本部分將通過幾個實例來分析腳本程序在SVG中的應用。
1、鼠標事件(演示鼠標事件的使用方法,以及常用的事件)
請看下面的例子:
<svg width="400" height="200">
<script><![CDATA[
function mout()
{
alert("you are out");
}
]]></script>
<g id="rect1">
<rect id="rectangle1" onmouseout="mout()" x="50" y="50" width="150" height="150" style="fill:red"/>
</g>
</svg>
用IE打開上面的SVG文件,當你的鼠標移開紅色的矩形框的時候,將會彈出提示信息"you are out"。
下面給出常見的鼠標事件和其觸發(fā)條件。
onmouseout 當鼠標移開一個物體(element)的時候觸發(fā)該事件
onmousedown 當在一個物體(element)上按下鼠標鍵時觸發(fā)該事件
onmouseup 當在一個物體(element)上松開鼠標鍵時觸發(fā)該事件
onmousemove 當鼠標在一個物體(element)上移動時觸發(fā)該事件
onclick 當鼠標點擊物體(element)的時候?qū)⒂|發(fā)該事件
更多的事件請參看http://www.w3.org/TR/SVG/interact.html。
對鼠標事件需要注意的是有時候可能同時有幾個事件同時發(fā)生,我們可以通過試驗得出響應事件的執(zhí)行順序。
2、放大、縮?。ㄑ菔灸_本語言對SVG中相關元素的屬性控制)
SVG的瀏覽器插件帶有放大、縮小的功能,但是在實際的應用中,我們需要自己編程實現(xiàn)SVG圖象文件的放大、縮小。下面的例子通過SVG的更改viewbox屬性來實現(xiàn)放大、縮小功能。(處理函數(shù)放在父HTML文件中)
SVG文件:1.svg
<html><head><title>SVG事件</title>
<body >
<script language="JavaScript" >
function fda()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","100 50 200 100");
}
function sxiao()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","-200 -100 800 400");
}
</script>
<embed name="id1" pluginspage=http://www.adobe.com/svg/viewer/install/ align="top" src="1.svg" height="200px" width="400px" type="image/svg+xml">
<input type="button" value="放大" name="fda" onclick="fda()">
<input type="button" value="縮小" name="sxiao" onclick="sxiao()">
</body>
</html>
HTML文件:aa.html
<html><head><title>SVG事件</title>
<body >
<script language="JavaScript" >
function fda()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","100 50 200 100");
}
function sxiao()
{
var SvgMainMapDoc=id1.getSVGDocument();
var OverMapview=SvgMainMapDoc.getElementById("mainview");
OverMapview.setAttribute("viewBox","-200 -100 800 400");
}
</script>
<embed name="id1" pluginspage=http://www.adobe.com/svg/viewer/install/ align="top" src="1.svg" height="200px" width="400px" type="image/svg+xml">
<input type="button" value="放大" name="fda" onclick="fda()">
<input type="button" value="縮小" name="sxiao" onclick="sxiao()">
</body>
</html>
用IE打開aa.html,按下放大,縮小按鈕將可以看到放大、縮小的效果。HTML中通過getSVGDocument()獲取SVG文檔的DOM(文檔對象模型),然后再通過getElementById和ID來獲取element的指針,然后通過setAttribute來設置element(即本例中ID為mainview的svg元素)。上面用到的幾個函數(shù)都是DOM函數(shù),更多的DOM函數(shù)及介紹可以在http://pilat.free.fr/routines/js_dom.htm上獲得。
下面介紹一下通過viewbox放大、縮小的原理。Viewbox中有四個數(shù)字,分別表示最小的x坐標,y坐標,最大x坐標和最小x坐標之差,最大y坐標和最小y坐標之差。也就是說viewbox表示的是當前的顯示范圍,因此只要改變viewbox的值就可以實現(xiàn)SVG圖象的放大和縮小。
3、屬性查詢、高亮顯示
屬性查詢在現(xiàn)實中有著許多的應用,通過查詢可以得出我們感興趣的東西。下面介紹如果實現(xiàn)對SVG屬性的查詢。
SVG文件:1.svg
<svg viewBox="0 0 400 400" id="mainview">
<g id="id1">
<rect id="rectangle" name="a1" x="0" y="0" width="50" height="50" style="fill:green"/>
<rect id="rectangle1" name="a2" x="50" y="50" width="50" height="50" style="fill:green"/>
<rect id="rectangle2" name="a3" x="100" y="100" width="50" height="50" style="fill:green"/>
<rect id="rectangle3" name="a4" x="150" y="150" width="50" height="50" style="fill:green"/>
<rect id="rectangle4" name="a5" x="200" y="200" width="50" height="50" style="fill:green"/>
<rect id="rectangle5" name="a6" x="250" y="250" width="50" height="50" style="fill:green"/>
<rect id="rectangle6" name="a7" x="300" y="300" width="50" height="50" style="fill:green"/>
<rect id="rectangle7" name="a1" x="350" y="350" width="50" height="50" style="fill:green"/>
</g>
</svg>
HTML文件:aa.html
<html><head><title>查詢SVG屬性</title>
<body >
<script language="JavaScript" >
function search(searchvalue)
{
var SvgMainMapDoc=id1.getSVGDocument();
SvgObj=SvgMainMapDoc.getElementById('g1');
SvgObj1=SvgObj.getChildNodes;
for(iCount=1;iCount<((SvgObj1.length)-1);iCount+=2)
{
if(SvgObj1.item(iCount).getAttribute("name")==searchvalue)
{
SvgStyle1=SvgObj1.item(iCount).getStyle();
SvgStyle1.setProperty('fill','green');
}
}
}
function clearaa()
{
var SvgMainMapDoc=id1.getSVGDocument();
SvgObj=SvgMainMapDoc.getElementById('g1');
SvgObj1=SvgObj.getChildNodes;
for(iCount=1;iCount<((SvgObj1.length)-1);iCount+=2)
{
SvgStyle1=SvgObj1.item(iCount).getStyle();
SvgStyle1.setProperty('fill','red');
}
}
</script>
<embed name="id1" pluginspage=" align="top" src="1.svg" height="200px" width="400px" type="image/svg+xml">
<form name="searchvalue">
<input name="value1" size="12"><input type="button" value="查詢" name="search1" onclick="search(this.form.value1.value)">
<input type="button" value="清除" name="clear" onclick="clearaa()">
</form>
</body>
</html>
用IE打開aa.html,輸入查詢的值如”a1”,選擇查詢將可以看到有兩個矩形高亮顯示,這是查詢的結(jié)果。清除可以消除高亮顯示。
下面分析一下查詢的過程。通過getSVGDocument()獲取SVG文檔的DOM(文檔對象模型),然后再通過getElementById和ID(”id1”)來獲取element的指針,再通過getChildNodes來獲得其子節(jié)點,最后通過item(序號)來訪問其子節(jié)點,并逐個判斷其name屬性的值是否跟要查詢的值相同,從而決定是否高亮顯示。這里需要注意的是子節(jié)點的序號是從1開始,并且以2遞增的。
上面給出了腳本編程的例子,如果想了解更多的腳本編程方面的資料,請訪問http://www.w3.org/TR/SVG/,里面有詳細的SVG資料!
XML 問題: 使用 SVG 編程
作者:David Mertz IBM DW中國 (2005-05-20 15:21:48)
可縮放矢量圖形(Scalable Vector Graphics,SVG)是一種用于描述與比例無關的圖形的 XML 格式,可以很好地支持免費軟件和商業(yè)工具。在本期文章中,David 將介紹使用 SVG 編寫腳本和動畫,還將涉及通過 DOM 處理 SVG 等內(nèi)容。SVG 由于是 XML 格式,因此可以支持通常用 XML 工具和庫進行的轉(zhuǎn)換和生成。
在 SVG 于 2001 年左右首次出現(xiàn)以前,已有相當多功能強大的矢量圖形格式。Postscript 及其類似產(chǎn)品 PDF 廣泛應用于許多應用程序。其他特定于應用程序的格式包括基于 Postscript 的 Adobe Illustrator (.ai)、CorelDRAW (.cdr)、Computer Graphics Metafile (.cgm)、Windows Metafile (.wmf)、Autocad (.dxf)、Hewlett-Packard Graphics Language (.hpgl)、WordPerfect (.wpg) 等。對于甚至可以組合動畫、聲音和交互性的矢量繪圖,則常使用 Macromedia 的 SWF/Flash 在萬維網(wǎng)上發(fā)布相關內(nèi)容。
SVG 與所有其他格式的主要區(qū)別在于,前者是 XML 的一個應用程序。盡管對于同等的圖形,使用 SVG 描述比使用多數(shù)其他矢量格式描述要復雜得多,但對于編程操作而言,SVG 則是一種更通用的工具。尤其是,您可以在使用 ECMAScript 和其他文檔對象模型 (DOM) 的 Web 瀏覽器(或其他應用程序)中操縱 SVG。而且同樣重要的是,您可以使用熟悉的 XML 技術(如 XSLT)或 XML 支持庫轉(zhuǎn)換和生成 SVG??梢詫?SVG 與其他使用名稱空間的 XML 格式混合。而且,甚至可以使用層疊樣式表 (CSS) 限定 SVG 的樣式??傊?,在 XML 和 Web 空間,SVG 是一個友好的播放器。
除了是 XML 格式以外,SVG 還是一個由 W3C 發(fā)布的完全開放的標準(請參閱 參考資料)。與上述多數(shù)矢量格式不同,SVG 是完全免費的,沒有任何版權或?qū)@麢嘞拗?,而且其?guī)范完全 有文檔記錄。與其他 W3C 標準類似,規(guī)范文檔本身是 受版權保護的 —— 但根據(jù) W3C 的非限制性條款的規(guī)定,允許廣泛傳播以及免費復制和使用(例如,規(guī)范中沒有附帶禁止公開協(xié)議)。
入門
令人高興的是,您可以在多數(shù)新式 Web 瀏覽器中查看 SVG,可以在本機也可以通過插件查看。精確的支持狀態(tài)在不斷變動,但通過正確的技術,您應能夠使用 Firefox/Mozilla、KHTML(Konqueror 和 Safari)、Opera 或 Amaya 查看 SVG。使用 Adobe 或 Corel 的插件,甚至還可以讓 Internet Explorer 顯示 SVG。還存在一些獨立的 SVG 查看器,特別是使用免費軟件 Batik SVG 工具包(是 Apache XML 項目的一部分 —— 請參閱“參考資料”)。
在許多情況下,SVG 文件是作為獨立的文檔查看的。在這樣的情況下,這些文件表現(xiàn)為 MIME 類型 image/svg+xml,并通常有一個文件擴展名 .svg。Gzip 壓縮的 SVG 文件應有擴展名 .svgz,可由多數(shù)啟用 SVG 的工具直接支持。SVG 文件只是具有適當 DTD 的 XML 文件。您將在下面幾個例子中了解到這一點。
然而,可能更為常見的是,您可以將一個 SVG 文檔嵌入較大的文檔中,特別是嵌入 XHTML 頁。其他復合 XML 格式(如 OASIS OpenDocument)也可以(或?qū)⒅С郑?SVG 嵌入其中。將 SVG 圖形嵌入 (X)HTML 頁有三種方式:
• 通過 <object> 標簽
• 通過 <embed> 標簽
• 作為嵌入的名稱空間
不過,具體使用哪一種方式有效取決于您的瀏覽器和版本。例如,我創(chuàng)建了下面的 XHTML 文檔(使用 doctype 來支持名稱空間嵌入):
清單 1. XHTML 文檔 (svg-nested.html)
<?xml version="1.0" standalone="no"?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
"http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html xmlns=" xml:lang="en">
<head>
<title>SVG as embedded object and nested namespace</title>
</head>
<body>
<h2>Object tag</h2>
<object type="image/svg+xml" data="standalone.svg">
Your browser is currently unable to display SVG images.
</object>
<h2>Nested namespace</h2>
<svg:svg version="1.1" width="5cm" height="4cm"
xmlns:svg="http://www.w3.org/2000/svg">
<svg:title>Four rectangles</svg:title>
<svg:rect x="0.5cm" y="0.5cm" width="2cm" height="1cm"/>
<svg:rect x="0.5cm" y="2cm" width="1cm" height="1.5cm"/>
<svg:rect x="3cm" y="0.5cm" width="1.5cm" height="2cm"/>
<svg:rect x="3.5cm" y="3cm" width="1cm" height="0.5cm"/>
<!-- Show outline of canvas using 'rect' element -->
<svg:rect x=".01cm" y=".01cm" width="4.98cm" height="3.98cm"
fill="none" stroke="blue" stroke-width=".02cm" />
</svg:svg>
<h2>Embed tag</h2>
<embed id="svg3" src="standalone.svg" />
</body>
</html>
通過嘗試,Safari/KHTML 在瀏覽器中表現(xiàn)最好。盡管如此,如果文件使用 .html 擴展名,而不是 .xml 擴展名命名,結(jié)果會更好??傊?,<embed> 也許是最成功的方法。您可能會看到文檔呈現(xiàn)為:
圖 1. Web 瀏覽器顯示的 svg-nested.html
另外,本文提供的示例是組合基本形狀、文本、顏色等內(nèi)容的較為簡單的示例 —— 但 SVG 完全能夠表現(xiàn)復雜和引人入勝的繪圖。為了提高讀者的興趣,下面是 Ghostscript 和其他工具中包括的著名的 PostScript 老虎圖片,它使用 SVG 呈現(xiàn)(我僅調(diào)整了它的總體大小):
圖 2. Web 瀏覽器將老虎圖像顯示為 SVG
SVG 文檔的特點
前面的 XHTML 例子(參閱 清單 1)為您顯示了非?;镜?SVG 繪圖。引用的外部文件 (standalone.svg) 所包含的元素與 XHTML 中嵌入的相同,只是去掉了標簽中額外的名稱空間限定符。SVG 為您提供了許多圖形元件,而且每個圖元都有可以進一步指定圖形的多種 XML 屬性:顏色、大小、位置、填充、輪廓等。不過,直觀的圖形元件(如橢圓、矩形或多邊形)或者一些可能包括立方體或二次貝塞爾曲線等的更為復雜的 <path> 元素,常常包括在 <g> 元素中,以便將若干個圖元組合在一起。<g> 組的優(yōu)點是,您可以對它進行整體縮放、移動、設定樣式或修改。 對組的修改通用于其中的形狀集合(包括嵌入的 <g> 組)。在編寫 SVG 文檔腳本時這特別有用。
始終如一
有關 SVG 文檔需要注意的一點是,它們并非完全 是真正的 XML。從語句上說,SVG 確實是 XML,但在 SVG 屬性中,SVG 繪圖信息內(nèi)容的重要部分包含在逗號和空格分隔的數(shù)據(jù)中。這里所說的信息內(nèi)容 并不是指 XML Infoset,僅指它包含什么?的更加非正式的概念。這樣做是一種合理的折衷方法,因為對定義曲線的每個點或句柄都使用子元素將會使 SVG 更加繁瑣。但是,XML 級處理技術(如 XSLT)因此能夠不用真正處理太多的路徑數(shù)據(jù)。例如,下面是一個二次貝塞爾曲線路徑元素:
<path d="M200,300 Q400,50 600,300 T1000,300"
fill="none" stroke="red" stroke-width="5" />
下面是一個描述五角星形的多邊形:
<polygon fill="red" stroke="blue" stroke-width="10"
points="350,75 379,161 469,161 397,215
423,301 350,250 277,301 303,215
231,161 321,161" />
添加樣式
前面提到過您可以使用 CSS 選擇器和語法來修改 SVG 繪圖的外觀。對于 HTML 和其他支持 CSS 的格式,既可以指定內(nèi)嵌 CSS 信息,也可以作為對外部樣式表的引用。下面是一個非常簡單的內(nèi)嵌 CSS 的例子:
清單 2.一個 簡單的 CSS 例子 (inline-styled.svg)
<?xml version="1.0" standalone="no"?>
<!-- By ref:
<?xml-stylesheet href="mystyle.css" type="text/css"?>
-->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="10cm" height="5cm" viewBox="0 0 1000 500"
xmlns=" version="1.1">
<defs>
<style type="text/css"><![CDATA[
rect {
fill: red;
stroke: blue;
stroke-width: 3
} ]]>
</style>
</defs>
<rect x="200" y="100" width="600" height="300"/>
</svg>
盡管使用 CSS 無疑可以限定整個標簽的樣式,但您可能會發(fā)現(xiàn),對 CSS 和 SVG 使用類選擇器會更好。例如,您可以在樣式表中定義各種類型的矩形,然后將一個 class XML 類屬性附加到繪圖中的每個矩形,而不用重復使用為類定義的整個顏色、填充、描邊和其他屬性列表。只須更改樣式表,就可以更改圖表的整體外觀,使之更適用于不同的環(huán)境。
重復使用元素
除使用 CSS 之外,清單 2 顯示了 SVG 另一種很好的功能:您可以在 SVG 文檔中包括預定義的內(nèi)容 —— 在呈現(xiàn)的文檔內(nèi)或文檔之外定義的內(nèi)容。
使用預定義內(nèi)容作為 SVG 繪圖一部分的方法之一是使用 <image> 元素。在概念上,SVG 中的 <image> 與 HTML 中的 <img> 非常類似:該元素只須指示呈現(xiàn)客戶機在當前的 SVG 環(huán)境中繪制外部圖像的內(nèi)容 —— 其本身可能是 SVG 或者是 JPEG 或 PNG 格式的光柵圖像。您幾乎可以像調(diào)整一個規(guī)則的圖形元素那樣來調(diào)整外部圖像的大小和改變其位置。例如:
清單 3. 在當前圖像中包括一個外部 SVG 繪圖
<image x="200" y="200" width="100px" height="100px"
xlink:href="http://example.org/external.svg">
比 <image> 標簽更有意思的也許是令人叫好的 <defs> 和 <use> 元素。首先,您可以使用 CSS 例子中所看到的內(nèi)容 創(chuàng)建 SVG 元素,這些元素在定義時沒有直接呈現(xiàn) —— 通常,SVG 呈現(xiàn)模型嚴格按照 SVG 文檔中出現(xiàn)的順序繪制每個對象,每個對象均覆蓋最后一個。但 <style> 不是典型的樣式,以后不能真正呈現(xiàn)其本身。
您可以在諸如 <defs> 節(jié)中包括想要包括的任何圖形元素,其中包括 <g> 組和 <symbol> 元素(符號與組類似;由于本文篇幅所限,這里不對其區(qū)別進行說明)。在定義的外部,您可以使用在 <defs> 節(jié)中定義的圖形元素 —— 甚至可使用在外部 SVG 文檔的 <defs> 節(jié)中定義的圖形元素。例如:
清單 4. 使用預定義的圖形元素
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="7cm" height="3cm" viewBox="0 0 70 30" version="1.1"
xmlns="http://www.w3.org/1999/xlink">
<desc>'use' with a 'transform' attribute</desc>
<defs>
<rect id="MyRect" x="0" y="0" width="40" height="5"/>
</defs>
<use xlink:href="#MyRect" transform="translate(10,23) rotate(-30)" />
<use xlink:href="#MyRect" transform="translate(20,3) rotate(30)" />
<use xlink:href="</svg>
在 清單 4 中,定義相同的矩形使用兩種不同的轉(zhuǎn)換呈現(xiàn),然后還呈現(xiàn)了外部定義的元素。(id 名稱表明它也是一個矩形,但從該片斷中不能明顯確定 —— 事實上,外部內(nèi)容可以在呈現(xiàn)之間更改)。
動畫和腳本
剛才已提到,使用 ECMAScript 可以編寫 SVG 腳本。原則上,這可讓 SVG 文檔與用戶操作交互。為了支持 Web 應用程序空間,SVG 還包含一個用于超鏈接的與 HTML 類似的 <a> 元素。根據(jù)鼠標在特定的圖形元素上單擊,SVG 中的簡單交互可以修改文檔。清單 5 中的例子雖然很普通,但您可以方便地讓 SVG 圖形響應。例如,在下面的流程圖中的圖形或?qū)ο髤^(qū)域上單擊:
清單 5. 讓 SVG 形狀響應單擊
<svg>
<title>ECMAScript function for an onclick event</title>
<desc>Simplified from
http://www.w3.org/TR/SVG11/images/script/script01.svg</desc>
<script type="text/ecmascript"> <![CDATA[
function circle_click(evt) {
var circle = evt.target;
var currentRadius = circle.getAttribute("r");
if (currentRadius == 100)
circle.setAttribute("r", currentRadius*2);
else
circle.setAttribute("r", currentRadius*0.5);
} ]]>
</script>
<!-- Act on each click event -->
<circle onclick="circle_click(evt)" cx="300" cy="225" r="100" fill="red"/>
</svg>
您還可以使用 ECMAScript 和 DOM 讓 SVG 圖形產(chǎn)生動畫效果。例如,清單 6 中的代碼可以使文本產(chǎn)生一個好看的效果,即增加和更改不透明度:
清單 6. 使用 JavaScript 讓 SVG 產(chǎn)生動畫效果
<svg viewBox="0 0 400 200"
onload="StartAnimation(evt)" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<script type="text/ecmascript"><![CDATA[
var txt, step=0;
function StartAnimation(evt) {
txt = evt.target.ownerDocument.getElementById("Text");
ShowAndGrowElement();
}
function ShowAndGrowElement() {
step = step+1;
if (step > 200) return;
// Scale text string gradually until it is 20 times larger
txt.setAttribute("transform", "scale("+ step/10 +")" );
// Make the string more opaque
txt.setAttribute("opacity", step/200);
// Call ShowAndGrowElement again 50 milliseconds later.
setTimeout("ShowAndGrowElement()", 50)
}
window.ShowAndGrowElement = ShowAndGrowElement
]]></script>
<g transform="translate(50,150)" fill="red" font-size="7">
<text id="Text">SVG</text>
</g>
</svg>
純粹的 SVG 腳本
使用 ECMAScript 可為您提供完美的編程靈活性,但如果您所需要的只是動畫,SVG 還提供了 <animate> 和相關的標簽(如 <animateMotion> 或 <animateColor>)。它們都非常靈活,可讓您以各種方式分別賦予 SVG 文檔中每個元素動畫效果。例如,清單 6 中的代碼可產(chǎn)生與 清單 5 中所示技術相同的增加和呈現(xiàn)不透明效果:
清單 6. 單獨使用 SVG 表現(xiàn)動畫效果
<svg viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(50,150)" fill="red" font-size="7">
<text id="Text">SVG
<animateTransform attributeName="transform" attributeType="XML"
type="scale" from="0" to="20" begin="0s" dur="10s"
fill="freeze" />
<animate attributeName="opacity" attributeType="CSS"
from="0" to="1" begin="0s" dur="10s" repeatCount="1" />
</text>
</g>
</svg>
結(jié)束語
本文初步探討了 SVG 格式的一些基本知識。撰寫本文讓我對 SVG 作為一種格式而感到興奮不已。Web 確實需要矢量格式以與比例無關的方式有效地傳達復雜圖形。再加上腳本、動畫、鏈接和所有其他內(nèi)容使 SVG 更加有用。所幸的是,多數(shù) Web 瀏覽器現(xiàn)在能夠很好地支持 SVG,因此部署基于 SVG 的圖形和簡單的 Web 應用程序?qū)嶋H上并不存在什么障礙。
可伸縮矢量圖(Scalable Vector Graphics SVG)是一種基于 XML 的語言,用于繪制二維圖形。不過,它的能力不局限于簡單的靜態(tài)矢量圖形。本文展示了如何將交互元素加入到 SVG 文檔中,使其可以對用戶輸入作出響應。
SVG 中的交互性可以分為三個領域 -- 鏈接、事件和腳本。本文將依次討論這三個領域。
注意:要查看本技巧中的 SVG 文檔,需要有一個 SVG 查看程序,可以在 參考資料中找到這種查看程序(還有一個包括所有相關文件的 .zip 文件)。
鏈接
最基本的交互形式是鏈接。在 SVG 中,通過一個 <a> 標簽提供鏈接,這與 HTML 鏈接的方式幾乎相同。將 <a> 標簽與一個 xlink:href 屬性結(jié)合使用便可以建立一個鏈接。在 <a>和 </a> 標簽之間的所有內(nèi)容都作為鏈接的一部分。清單1展示了一個例子,它有三個元素,設置為鏈接到三個不同的 URL。 單擊這里以在瀏覽器中查看它們。
文本、矩形和多邊形元素都有到不同頁面的鏈接,這表明所有 SVG 元素 -- 不管是文本、圓還是不規(guī)則的多邊形 -- 都可以作為一個鏈接。注意,如果將鼠標移動到這些元素上面,指針會相應地發(fā)生改變,表明這是一個鏈接。
其功能與 HTML 中的 image map(或者 hotspot)基本上相同。不過,在 HMTL 中這會是一個很麻煩的過程,要用專門的軟件在一個圖像上手工繪制熱點 -- 如果這個圖像或者鏈接改變了,那么更新它們會非常麻煩。在 SVG 中,定義和維護鏈接則容易得多,這主要是因為鏈接可以隨著 SVG 內(nèi)容動態(tài)移動。
清單1. 鏈接
<svg>
<a xlink:href="http://www.w3.org//Graphics//SVG//Overview.htm8">
<rect x="10" y="10" width="100" height="30" rx="10" ry="10"
style="fill:lightgrey"/>
<text x="30" y="30" font-size="12">Click here</text>
</a>
<a xlink:href="http://www.ibm.com//developerworks/">
<circle cx="100" cy="100" r="50" style="fill:grey"/>
<text x="80" y="100" font-size="12">Or here</text>
</a>
<a xlink:href=" target="new">
<polygon
points="60 160,165 172,180 60,290 290,272 280,172 285,250 255"
style="fill:dimgrey"/>
<text x="160" y="200" font-size="12">Or even here</text>
</a>
</svg>
注意在多邊形的 xlink 中使用的 target=new 屬性。它指示查看程序在單擊這個元素時打開一個新的瀏覽器窗口。
回頁首
事件
SVG 支持鼠標單擊、鼠標移動和鼠標按下這樣的用戶鼠標事件。清單2展示了一個例子:
清單2. 使用鼠標的交互性
<svg>
<rect x="10" y="10" width="140" height="140" rx="5" ry="5"
style="fill:lightgrey">
<set attributeName="fill" from="lightgrey" to="red"
begin="mouseover" end="mouseout"/>
</rect>
<text x="200" y="75" font-size="30">Move over me and click
<set attributeName="font-size" from="30" to="35"
begin="mouseover" end="mouseout"/>
<set attributeName="fill" from="black" to="red"
begin="mousedown" end="mouseup"/>
</text>
</svg>
單擊這里以便觀看效果。矩形和文本元素對不同的事件 -- 如移動鼠標和單擊 -- 做出反應,產(chǎn)生一種簡單的滾動效果。試著將鼠標移動到元素上面以觀看這些效果。任何可以應用到元素上的 SVG 屬性 -- 如填充顏色、筆劃寬度、大小和透明度 -- 都可以以這種方式改變。
文字元素可以對兩種事件做出反應 -- mouseover 和 mousedown 。這表明可以對同一個元素指定多個事件。SVG 支持許多不同的事件 -- 有關所有事件類型的完整列表可以參看 參考資料中的 W3C 的 SVG 站點。
如果希望一個元素上的事件可以引發(fā)對另一個元素的操作,可以對 SVG 元素指定 id 屬性,然后引用它們。清單3展示了一個例子。
清單3: 改變另一個元素的屬性
<svg>
<rect id="changeToRed" x="20" y="20" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="35" font-size="14">Move over for red text</text>
<rect id="bigText" x="20" y="60" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="75" font-size="14">Move over for big text</text>
<rect id="bigRedText" x="20" y="100" width="25" height="25" rx="5"
ry="5" style="fill:lightgrey"/>
<text x="50" y="115" font-size="14">Click me for big red text</text>
<text id="changingText" x="250" y="100" font-size="30"
fill="black">Change me
<set attributeName="fill" from="black" to="red"
begin="changeToRed.mouseover" end="changeToRed.mouseout"/>
<set attributeName="font-size" from="14" to="50"
begin="bigText.mouseover" end="bigText.mouseout"/>
<set attributeName="font-size" from="14" to="50"
begin="bigRedText.click" end="bigRedText.mouseout"/>
<set attributeName="fill" from="black" to="red"
begin="bigRedText.click" end="bigRedText.mouseout"/>
</text>
</svg>
單擊這里可以在瀏覽器中觀看效果。當鼠標移動到不同的矩形上時,文本就會改變。有三個矩形被指定了各自的 id 屬性,文字的 set 元素通過“ id.eventName ”引用這些屬性。觸發(fā)矩形的事件時,文本的屬性就會相應地改變。
還可以用一個動畫響應事件。清單4展示了這樣的一個例子:
清單4. 開始一個動畫
<svg>
<rect x="20" y="20" width="250" height="250" rx="5" ry="5"
style="fill:red">
<animate attributeName="opacity" from="1" to="0"
begin="click + 1s" dur="1s" fill="restore" />
</rect>
<circle cx="250" cy="250" r="100" style="fill:blue">
<animate attributeName="fill" from="blue" to="green"
begin="mouseover" dur="2s" fill="restore" />
</circle>
</svg>
單擊這里以便觀看效果。單擊矩形時,它會淡出,在圓形上面移動鼠標時,它的顏色會改變。注意可以在 begin 屬性中使用“ +Xs ”使動畫延遲開始。
鍵按下
雖然 SVG 上的大部分交互是通過鼠標進行的,但是 SVG 也支持鍵盤輸入。這是通過事件處理程序 accessKey 實現(xiàn)的,如清單5所示。
清單5. 捕獲鍵按下
<svg>
<rect x="20" y="20" width="100" height="100" rx="5" ry="5"
style="fill:red">
<animate attributeName="opacity" from="1" to="0"
begin="accessKey(1)" dur="3s" fill="restore" />
</rect>
<rect x="140" y="20" width="100" height="100" rx="5" ry="5"
style="fill:red">
<animateTransform attributeName="transform" type="rotate"
from="0" to="90" begin="accessKey(2)" dur="3s"/>
</rect>
<rect x="260" y="20" width="100" height="100" rx="5" ry="5"
style="fill:red">
<animateColor attributeName="fill" from="red" to="green"
begin="accessKey(3)" dur="3s" />
<animate attributeName="y" from="20" to="100"
begin="accessKey(
)" dur="3s" fill="restore" />
</rect>
</svg>
單擊這里以觀看效果。三個矩形設置為響應鍵盤上的數(shù)字鍵 1、2 和 3。試一試按下每一個鍵,并觀察圖像相應的反應。
可以設置一個元素響應任意數(shù)量的不同的鍵。注意第三個矩形設置為監(jiān)聽兩個鍵按下。第三個矩形上的第二個 accessKey 處理程序設置為監(jiān)聽鍵 ( ) -- 您可能認出它就是回車鍵(Enter)的標準 HTML 編碼。要指定任何特殊字符或者空格字符,必須使用 X 這樣的 HTML 編碼格式,其中 XX 是 ASCII 字符編碼。
回頁首
腳本
到目前為止我只討論了用 SVG 支持的內(nèi)置功能響應事件的基本方法。雖然可以只使用這些功能完成很多工作,但是要實現(xiàn)更高級的效果就需要使用腳本了。SVG 支持像 VBScript 和 JavaScript 這樣的腳本語言,對于這里的例子,我將使用 JavaScript。
要讓一個 SVG 對象對腳本中的事件作出響應,要在觸發(fā)器名上加前綴 on ,這樣 click 就變?yōu)?onclick , mouseover 就變?yōu)?onmouseover ,等等。清單6展示了一個 SVG 腳本的例子。
清單6. 用 JavaScript 編寫 SVG 腳本
<svg>
<script type="text/javascript">
<![CDATA[
var redVal=0;
var greenVal=0;
var blueVal=0;
function changeCol(evt)
{
var targetshape = evt.getTarget();
redVal = Math.round(Math.random()*255);
greenVal = Math.round(Math.random()*255);
blueVal = Math.round(Math.random()*255);
targetshape.setAttribute("fill",
"rgb(" + redVal + "," + greenVal + "," + blueVal + ")");
}
// ]]>
</script>
<circle cx="200" cy="200" r="100" fill="blue"
onclick="changeCol(evt)" />
</svg>
下面逐步分析 清單6:
1. 編寫 SVG 腳本的第一步是通知查看程序不再使用 SVG,而是使用腳本語言。還必須用 type 屬性定義使用哪種腳本語言編碼。在這里它設置為 text/javascript 。
2. <![CDATA[ 是 XML 命令,它告訴查看程序停止解析代碼,并讀取接下來的塊中的代碼,這里的代碼是字符數(shù)據(jù)的形式。這可以防止查看程序?qū)⒗ㄌ柡推渌厥庾址?SVG 元素處理,并使腳本編寫更容易。
3. 現(xiàn)在就可以開始腳本了。首先,定義三個變量: redVal 、 greenVal 和 blueVal 。這些變量分別具有red、green 和 blue 值,它們將在函數(shù)中用到。這個函數(shù)名為 changeCol ,它帶有一個參數(shù) (evt)。 evt 是一個 SVG 保留字,它描述剛發(fā)生的事件。這里, evt 方法稱為 getTarget(), 這個方法返回對觸發(fā)該事件的 SVG 對象的一個引用。這個引用被存儲在變量 targetShape 中。
4. 用簡單的 JavaScript 函數(shù) Math 生成三個值在 0 到 255 之間的隨機數(shù)。
5. 最后,對 targetshape 調(diào)用 setAttribute 方法。用前一步中生成的三個隨機數(shù)將該對象的 fill 屬性設置為一個 RGB 值(如 rgb(150,200,50) )。
6. 關閉 CDATA 塊和腳本后,返回 SVG。畫出一個圓,通過 onClick 元素,在單擊時讓它調(diào)用函數(shù) changeCol(evt)。
單擊這里以便觀看效果。單擊這個圓時,每次單擊它時填充都會變?yōu)橐粋€隨機顏色。
當一個函數(shù)要應用到多個 SVG 元素時,腳本是最有用的。例如,可以在清單6中添加一個矩形,如下所示:
<rect x="400" cy="400" width="100" height="100" fill="blue"
onclick="changeCol(evt)" />
單擊時,這個矩形會與前面的圓形一樣調(diào)用同一個腳本改變其顏色。
要查看這一點,可以看一下 其他例子。如果查看源代碼,您會看到三個方法: changeCol 、 changeEdge 和 resetEdge 。試著將鼠標移動矩形上面并單擊。所有矩形都設置為響應 onclick 、 onmouseover 和 onmouseout 事件,它們?yōu)榇苏{(diào)用的是同一個腳本函數(shù)。還要注意 onload 屬性:第一次裝載 SVG 文檔時要調(diào)用這個屬性,它對于您的 SVG 初始化很有用。
交互文本
在 SVG 中創(chuàng)建交互文本比您想象中的要復雜一些。在定義文本元素時,顯示的文本是文本元素的子元素,而不是像 font-size 這樣的屬性,因此不能像前面那樣簡單地調(diào)用 setAttribute 來修改其內(nèi)容。相反,必須創(chuàng)建一個新的文本元素,并用它替換當前的文本元素。清單7展示了一個例子。
清單7. 編寫文本變化的腳本
<svg>
<script type="text/javascript">
<![CDATA[
function changeText(evt)
{
targetXtext=svgDocument.getElementById("XPos");
targetYtext=svgDocument.getElementById("YPos");
var XPos = evt.getClientX();
var YPos = evt.getClientY();
var newXPosText = svgDocument.createTextNode("X Position : " + XPos);
var newYPosText = svgDocument.createTextNode("Y Position : " + YPos);
targetXtext.replaceChild(newXPosText,targetXtext.getFirstChild());
targetYtext.replaceChild(newYPosText,targetYtext.getFirstChild());
}
function changeTextNotOver(evt)
{
targetXtext=svgDocument.getElementById("XPos");
targetYtext=svgDocument.getElementById("YPos");
var newXPosText =
svgDocument.createTextNode("X Position : Not over Rectangle");
var newYPosText =
svgDocument.createTextNode("Y Position : Not over Rectangle");
targetXtext.replaceChild(newXPosText,targetXtext.getFirstChild());
targetYtext.replaceChild(newYPosText,targetYtext.getFirstChild());
}
function recordClick(evt)
{
targetClickText=svgDocument.getElementById("ClickPos");
var XPos = evt.getClientX();
var YPos = evt.getClientY();
var newClickText =
svgDocument.createTextNode("Last Click made at X=" + XPos + " Y=" + YPos);
targetClickText.replaceChild(newClickText,
targetClickText.getFirstChild());
}
// ]]>
</script>
<text id="XPos" x="50" y="50"<X Position :</text>
<text id="YPos" x="50" y="70"<Y Position :</text>
<text id="ClickPos" x="50" y="90"<Last Click made at : </text>
<rect x="50" y="100" width="200" height="200" style="fill:blue"
onmousemove="changeText(evt)" onmouseout="changeTextNotOver(evt)"
onclick="recordClick(evt)"/>
</svg>
單擊這里以便觀看效果。將鼠標移動到矩形上面時,會顯示鼠標的 X 和 Y 位置,并且這兩個顯示的值會隨著鼠標的移動而改變,在矩形上單擊鼠標會記錄下單擊的位置。
分析函數(shù) changeText(evt) 可揭示創(chuàng)建交互文本的步驟:
1. 為所使用的每一個文本元素指定 id ,這樣腳本就可以提取它們。
2. 第一次調(diào)用 svgDocument.getElementById() ,其中傳遞的參數(shù)是要改變的文本元素的 ID。它被存儲在一個變量中以供以后使用。
3. 調(diào)用 evt 方法 getClientX() 和 getClientY() 以得到指針的 X 和 Y 坐標,并將它們存儲在變量 XPos 和 YPos 中。
4. 調(diào)用 svgDocument.createTextNode() 創(chuàng)建一個新文本節(jié)點。將更新過的文本字符串傳遞給這個函數(shù)。
5. 最后,對這個文字元素調(diào)用 replaceChild 方法。它帶兩個參數(shù) -- 替換文本節(jié)點和被替換的子元素。對 getFirstChild() 的調(diào)用保證更新的文本放置正確。
參照清單7,您應該可以將交互文本加入到自己的 SVG 文檔中。
回頁首
結(jié)束語
可以使用本文中描述的各種交互技術使您的 SVG 文檔對用戶有更大的用途。設法將這些技術結(jié)合在一起以得到您想要的功能。
看一下 這個小例子以了解如何綜合使用這些技術制作一個交互菜單。
回頁首
參考資料
• 您可以參閱本文在 developerWorks 全球站點上的 英文原文.
• 下載本文中的所有 樣本文件。
• 閱讀 可伸縮矢量圖(SVG)1.0規(guī)范或者最新的 1.2規(guī)范。
• 閱讀 W3C 站點上完整的 支持的事件列表。
• 請訪問 Adobe 的 SVG Zone以獲得眾多的 SVG 資源,其中包括一個可以下載 SVG查看程序的專區(qū)。
• 學習 Brian Venn 在 developerWorks上的文章“ 產(chǎn)生可伸縮向量圖形”,它介紹了如何在 SVG 文檔中創(chuàng)建動畫(2003年6月)。
• 請學習 Nicholas Chase 的 developerWorks 教程“ Introduction to SVG”,該教程是學習 SVG 的一個好起點(2002 年 2 月)。
• 學習 Andrew Watts 在 developerWorks 上的教程“ Interactive, dynamic Scalable Vector Graphics”以將交互性提高到一個新的水平(2003年6月)。
• 在 developerWorks 的 XML專區(qū) 可以找到更多 XML 參考資料。
• IBM的 DB2 數(shù)據(jù)庫不僅提供了關系數(shù)據(jù)庫存儲,而且提供了像 DB2 XML Extender 這樣提供 XML 和關系系統(tǒng)之間橋梁的 XML 相關工具。請訪問 DB2開發(fā)者園地以了解更多關于 DB2 的內(nèi)容。
• 查明如何才能成為一名 IBM 認證的 XML 和相關技術的開發(fā)人員。
回頁首
關于作者
Brian Venn 在英國太空防御系統(tǒng)(British Aerospace Defence Systems)工作了三年后,于 2000 年 10 月加入 IBM。他畢業(yè)于南安普敦大學,獲得了天體物理學學士學位,并且通過了 DB2 和軟件測試方面的認證。他目前在 Hursley Park 從事集成測試工作。
聯(lián)系客服