日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用脚本动态操作 SVG 文档

發(fā)布時間:2023/12/9 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用脚本动态操作 SVG 文档 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
本教程適用于那些希望使用可伸縮向量圖形(SVG)創(chuàng)建交互式 SVG 圖形的開發(fā)人員。它討論了使用ECMAScript(JavaScript)對現(xiàn)有的 SVG 圖像進行實時操作得技術。

本文主要介紹在 SVG 中通過編程實現(xiàn)動態(tài)操作 SVG 圖像的知識。

SVG 圖像的結構是用 XML 文檔表示的,因此可以使用 XML 編程技術如"文檔對象模型(Document Object Model,DOM)"來操縱它。本文描述了如何使用 ECMAScript/JavaScript 來支持與 SVG 圖像的交互。理論上說我們可以用這些知識實現(xiàn)類似射擊游戲這樣復雜的圖形交互程序。

有兩種方法可以對SVG文檔的DOM對象進行操作:通過JavaScript在SVG文檔內(nèi)部進行處理;在Batik環(huán)境下通過相關接口獲取當前顯示SVG視圖的DOM對象引用使用Java語言對SVG文檔進行處理。本文重點描述使用JavaScript對SVG進行操作的相關技術,并在文章最后用一個簡單的例子實現(xiàn)Batik下通過Java實現(xiàn)操作DOM對象。另外還用相當?shù)钠懻摿顺S肧VG瀏覽工具中支持的特殊 ECMAScript/JavaScript 用法,這些方法可以顯著提高我們的開發(fā)速度。

1. 理解 SVG 對象結構

在 SVG 瀏覽器上下文環(huán)境("上下文環(huán)境"一詞來自"context"的直譯)中,除了 SVG 本身作為 XML 文檔所包含的 DOM 對象外,還包含一些其他對象,這些支持對象隨著瀏覽工具的不同而在細節(jié)上有所區(qū)別。


圖 1. SVG 對象結構

Window 是一個全局變量,該變量表示 SVG 運行時的瀏覽器窗口對象。因為腳本的運行就是在 window 對象內(nèi)部進行的,所以調(diào)用該對象方法和屬性時可以省去對 window 變量的指定,例如 window.document 可以直接通過 document 實現(xiàn)引用。完全介紹 window 對象的屬性和方法內(nèi)容已經(jīng)超出了本文的范圍,有興趣的讀者可以通過參考資料查閱詳細說明。

Document 是 window 對象中的靜態(tài)全局變量,通過該變量我們可以立即獲取當前瀏覽 SVG 圖形的 SVG 文檔對象(SVGDocument)。通過獲取 SVG 文檔對象我們就可以在 DOM 框架下對當前 SVG 文檔的內(nèi)容進行動態(tài)操作。

contextMenu 變量只在 Adobo SVG Viewer3.0中有效,該變量同 document 變量一樣,也是 window 對象的靜態(tài)全局變量。它引用了在Adobo SVG Viewer3.0瀏覽環(huán)境下單擊鼠標右鍵時所展示菜單的 XML 文檔對象(Document),通過重新構建該變量引用的對象內(nèi)容,我們可以重新構建瀏覽時鼠標右鍵菜單的字體和條目。





回頁首


2. 將 JavaScript 腳本放在哪里

使用 JavaScript 首先我們要解決一個簡單的問題:我們把腳本代碼放在哪里?SVG 標準允許將JavaScript 腳本代碼以兩種方式來實現(xiàn):使用 script 元素將 JavaScript 腳本內(nèi)嵌在 SVG 文件中;或使用script 的 xlink:href 屬性從 SVG 文件之外連接 JavaScript 腳本文件。從腳本實現(xiàn)的功能上來說,這兩種代碼加載方式?jīng)]有區(qū)別,我們可以將共享的腳本代碼放在外邊連接文件中,把該 SVG 文件個性化的代碼嵌在自身的文件中。

下面是一個 SVG 文件和一份 JavaScript 腳本文件,將這兩個文件放在同一個文件夾下打開即可運行。


表1: jslocation.svg
1. <?xml version="1.0" encoding="UTF-8"?>2. <svg3. xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">4. <script language="JavaScript" xlink:href="lib.js" />5. <script language="JavaScript"><![CDATA[6. function Body_function(str){7. alert("Body_function->"+str)8. }9. ]]></script>10. <g id="funciton_load" transform="translate(10 10)">11. <g οnclick="Body_function('onclike')" transform="translate(0 0)">12. <text x="6px" y="30px" style="font-size:20">Body_function</text>13. </g>14. <g οnclick="Lib_function('onclike')" transform="translate(160 0)">15. <text x="6px" y="30px" style="font-size:20">Lib_function</text>16. </g>17. </g>18. </svg>

因為在 SVG 引用外部腳本文件時是以 utf 編碼方式引入的,所以我們不能在待引用的腳本文件中使用中文,甚至在注釋中使用中文也會使代碼運行出現(xiàn)不確定的異常。所以在實際運行時,需要刪除本文后續(xù)例子中為代碼所做的中文注釋。


表2: lib.js
function Lib_function(str){alert("Lib_function->"+str)}

jslocation.svg 文件的第5-9行之間內(nèi)嵌了一段 JavaScript 腳本,第4行引用了一個外部 js 文件。第 11 行和第 14 行分別通過 onclick 事件調(diào)用了這兩種代碼加載方式所包含的兩個不同的函數(shù)。

特別需要留意的是第 3 行的對名稱空間的聲明。名稱空間的聲明指定了這些 SVG 元素位于 SVG 名稱空間內(nèi),編寫這些元素時無需帶任何名稱空間的前綴。在使用Adobo SVG Viewer3.0瀏覽 SVG 圖像時可以缺省定義這些命名空間,Adobo SVG Viewer3.0瀏覽環(huán)境會默認的將文檔內(nèi)的 XML 元素識別為SVG 元素。但當我們使用Batik 瀏覽 SVG 圖像時,這些命名空間是必須要指定的,否則,腳本的鏈接和其他一些復雜的功能將不能起作用。





回頁首


3. 通過 JavaScript 動態(tài)操作 SVG 文檔

3.1 通過 DOM 對象操作節(jié)點

在 JavaScript 環(huán)境下,通過 DOM 定義的接口,我們可以在 SVG 的 XML 樹中漫游,可以對找到的節(jié)點屬性重新賦值,還可以在當前文檔中刪除節(jié)點或添加新創(chuàng)建的節(jié)點。

下面的例子展示了通過 DOM 接口如何刪除現(xiàn)有節(jié)點,添加新的節(jié)點并為新節(jié)點設置了超級鏈接地址:


表3: 對 SVG 文檔進行動態(tài)操作
<g οnclick="operate_Dom()" id="g5" transform="translate(0 80)"><text id="txt1" x="6px" y="30px" style="font-size:15">operate DOM</text><text id="txt2" x="6px" y="50px" style="font-size:15">operate DOM</text></g><!-內(nèi)嵌腳本代碼'<script language="JavaScript"><![CDATA[function operate_Dom(){//通過document環(huán)境變量獲取id值為"g5"的節(jié)點var g5=document.getElementById("g5");//將g5節(jié)點下所有text節(jié)點刪除var txts=g5.getElementsByTagName("text");for(var i=txts.length-1;i>=0;i--){g5.removeChild(txts.item(i));}//將g5節(jié)點的onclick事件刪除g5.removeAttribute("onclick");//創(chuàng)造一個文本節(jié)點對象var text = document.createElement ("text");text.setAttribute("x", 100);text.setAttribute("y", 100);//將文本內(nèi)容添加到text節(jié)點對象中text.appendChild(document.createTextNode("new text"));//創(chuàng)造一個鏈接節(jié)點,注意在這里給設置節(jié)點和屬性時必須指定命名空間var a=document.createElementNS("http://www.w3.org/2000/svg","a");a.setAttributeNS("http://www.w3.org/2000/xlink/namespace/","xlink:href","http://www.sina.com");//將text節(jié)點添加到鏈接節(jié)點中a.appendChild(text);//將鏈接節(jié)點添加到g5節(jié)點中g5.appendChild(a);//獲取視圖范圍var bBox=(document.getDocumentElement().getBBox());//創(chuàng)建一個矩形節(jié)點var shape = document.createElement("rect ");//配置屬性shape.setAttribute("x", bBox.x);shape.setAttribute("y", bBox.y);shape.setAttribute("width", bBox.width);shape.setAttribute("height", bBox.height);shape.setAttribute("style", "fill: #eeeeee");shape.getStyle().setProperty("stroke","red");shape.getStyle().setProperty("stroke-width","1");//將矩形節(jié)點添加到SVG根節(jié)點子節(jié)點隊列的最前邊document.getDocumentElement().insertBefore(shape,document.getDocumentElement().firstChild);}]]></script>

關于 DOM 接口的詳細定義,我們可以通過參考資料提供的相關鏈接獲取。除了在 DOM 接口中定義的相關方法和屬性之外,SVG 在具體實現(xiàn) JavaScript 時根據(jù)圖形處理的需要對 DOM 接口也進行了相應的擴展。比較重要的擴展是關于 SVG 視圖比例池相關的方法,這些方法可以讓我們通過 document.getDocumentElement()獲取 SVG 文檔的坐標系統(tǒng)的附加信息。


表4: 文檔根節(jié)點擴展的坐標系統(tǒng)附加信息

除了這里提到的比較重要的接口之外,我們還可以通過使用的 SVG 瀏覽器產(chǎn)品的開發(fā)文檔獲取詳細信息。但遺憾的是這些文檔往往寫的非常簡略,很多操作接口只是給出了 IDL 定義并沒有對接口的內(nèi)容進行詳細闡述,這就需要我們發(fā)揮想像力去猜測并進行具體的測試驗證了。比較常用的方法是分析 Batik 的源代碼跟蹤相關函數(shù)的具體實現(xiàn)來獲取函數(shù)的執(zhí)行過程。

需要特別指出的是用于創(chuàng)建超級鏈接節(jié)點的相關代碼,當需要創(chuàng)建超級鏈接節(jié)點的時候需要明確指出節(jié)點的命名空間"http://www.w3.org/2000/svg",為節(jié)點設置鏈接屬性的時候也必須指定屬性的命名空間"http://www.w3.org/2000/xlink/namespace/"。關于命名空間在 SVG 中的意義我們可以通過在 Batik 中的腳本改寫來深刻體會其中的內(nèi)涵。

3.2 針對 Batik 的腳本改寫:

在 Batik 環(huán)境下運行剛才的例子時,你會發(fā)現(xiàn)根本得不到我們在 Adobo SVG Viewer3.0 下看到的效果。這是因為在 Adobo 的環(huán)境下對 DOM 編程的要求不是很嚴格,所以我們可以用比較模糊的代碼來實現(xiàn)這些功能,IE瀏覽器的 JavaScript 引擎會對我們調(diào)用的函數(shù)進行自動匹配(這類似于 C 語法中的默認參數(shù)值)。但在Batik 環(huán)境下使用的 JavaScript 的引擎是引自 Apache 的腳本引擎庫,該腳本引擎對 JavaScript 的代碼要求非常嚴格。為了能在 Batik 環(huán)境下運行,我們必須對 JavaScript 腳本進行嚴謹?shù)男薷?#xff0c;使其能經(jīng)過 Batik腳本引擎的考驗。我們將紅色部分的代碼注釋掉換上新的代碼就可以看到在Batik環(huán)境下JavaScript 對 DOM對象的操作起作用了。

在 Batik 環(huán)境下需要創(chuàng)建新節(jié)點時,必須指定新節(jié)點引用的命名空間"http://www.w3.org/2000/svg"才能有效。


表5: 針對 Batik 的改寫
創(chuàng)建新節(jié)點的時候必須明確指定該節(jié)點的命名空間//var shape = document.createElement("rect");var shape = document.createElementNS("http://www.w3.org/2000/svg"," rect ");//var text = document.createElement ("text");var text = document.createElementNS("http://www.w3.org/2000/svg","text");定義樣式屬性時必須指定該屬性的優(yōu)先級,一般設置一個空白字符串就可以了。//shape.getStyle().setProperty("stroke","red");//shape.getStyle().setProperty("stroke-width","10");shape.getStyle().setProperty("stroke","red","");shape.getStyle().setProperty("stroke-width","10","");

為 Batik 改寫的腳本代碼在Adobo SVG Viewer3.0環(huán)境下是可以正確運行,這意味著通過對代碼進行細致的處理,我們能夠編寫在兩種平臺下都能運行的腳本。





回頁首


4. 由瀏覽工具提供的腳本支持

在 W3C 的 SVG 標準之外,各種品牌的 SVG 瀏覽器還提供了一些在 SVG 編程中支持的特殊函數(shù)和對象,用于實現(xiàn)一些特殊功能或提高開發(fā)效率。其中有些函數(shù)是各個產(chǎn)品都實現(xiàn)了的,這就大大降低了我們在移植過程中的難度。

4.1 數(shù)據(jù)通訊函數(shù)

函數(shù)名稱:getURL(uri, GetURLHandler)
支持環(huán)境:Adobe SVG Viewer3.0;Batik1.5.1
用途:該函數(shù)是 window 對象的提供的方法,可以允許你從指定的 URL 路徑實時加載數(shù)據(jù)。GetURLHandler 參數(shù)用于指定一個用于處理加載數(shù)據(jù)的函數(shù)指針。


表6: 使用 getURL
function loadFile () {getURL("menuitem_en-us.xml", fileLoaded);}function fileLoaded (data) {if(data.success) {alert(data.contentType);alert(data.content);}}

示例中的 fileLoaded 函數(shù)用于處理實時加載的文件,其中的 data 參數(shù)是一個關于指定 URL 文件信息的對象,該對象的 success 屬性用于標識是否成功加載指定文件;content 屬性用于記錄加載文件的文本內(nèi)容;contentType 屬性標識文件類型(該屬性在 Batik 中未被支持)。

由 Adobo 實現(xiàn)的 getURL 方法在加載文件時可以智能的判斷加載文件的文件類型和編碼方式,你可以加載gzip 壓縮的 xml 文件,比如壓縮存儲格式的.svgz 文件在加載后會自動進行必要的解壓操作。在加載文本文件的時候還可以根據(jù)加載文件的編碼格式(ASCII ,UTF-8,UTF-16)進行自動識別。

警告:在Adobe SVG Viewer 的早期版本(3.0以前)中可以為 getURL 的 url 參數(shù)設定任意路徑的文件,遠程攻擊者可以利用這個漏洞讀取系統(tǒng)本地或遠程文件,泄露敏感信息。不過 IE6 SP1 對從 Internet 域讀取本地文件內(nèi)容做了限制,因此 IE6 SP1 不存在此問題,也可以通過下載 Adobe SVG Viewer3.01 版本來彌補這個漏洞。彌補漏洞后只可以為 getURL()設定 SVG 文件所在 URI 域的文件路徑。

4.2 XML 轉換函數(shù)

函數(shù)名稱:String printNode(Node)
支持環(huán)境:Adobe SVG Viewer3.0
用途:參數(shù)中的node節(jié)點解析為字符串。

函數(shù)名稱:Node parseXML(String ,document)
支持環(huán)境:Adobe SVG Viewer3.0;Batik1.5.1
用途:將字符串解析成一個節(jié)點對象。

這一對函數(shù)用于進行字符串和DOM節(jié)點之間的轉換。我們可以使用printNode()序列化指定節(jié)點用于將當前SVG文檔中的Node元素生成字符串用于保存為文本文件或提交給遠程服務器。相反的我們可以通過parseXML()將一個字符串用指定的Document解析為一個Node對象,為parseXML()配置的document參數(shù)用于指定解析Node對象的Document;在Adobo SVG Viewer環(huán)境下可以不指定document對象,系統(tǒng)會默認用當前SVG文檔的Document對象解析字符串。


表7: 將字符串編譯成SVG節(jié)點并添加到當前SVG文檔
function parseAndAddData (string) {var node = parseXML(string, document);document.documentElement.appendChild(node);}

4.3 在Adobo SVG Viewer中重構菜單

Adobe SVG Viewer3.0為瀏覽用戶提供了單擊鼠標右鍵彈出的菜單用于實現(xiàn)常用的瀏覽操作功能,在實際應用中我們有時會需要定義自己的鼠標右鍵菜單的語言或裁減相應的菜單功能。Adobe SVG Viewer3.0的腳本環(huán)境中提供了一個環(huán)境變量"contextMenu"。 變量contextMenu是一個document對象,我們可以通過重新定義contextMenu文檔對象的節(jié)點內(nèi)容來重構菜單的內(nèi)容和樣式,并在設定菜單條目顯示的文字時通過"&*"來定義相應條目的快捷鍵。


表8: 根據(jù)系統(tǒng)默認語言動態(tài)加載不同的菜單文檔
function setMenuLanguage(){if(top.navigator.userLanguage=="zh-cn"){}else if(top.navigator.userLanguage=="zh-tw"){getURL("menuitem_zh-tw.xml", fileLoaded);}else{getURL("menuitem_en-us.xml", fileLoaded);}}function fileLoaded (data) {var msg = '';if(data.success) {var newMenuRoot=parseXML(data.content,contextMenu);contextMenu.replaceChild(newMenuRoot,contextMenu.getDocumentElement());}}

下面是針對英文操作系統(tǒng)配置的菜單定義文件,讀著可以根據(jù)模板定義其他語言的菜單。


表9: 使用英文的菜單文件"menuitem_en-us.xml"
<?xml version="1.0" encoding="UTF-8"?><menu id="myCustomMenu"><header>Adobe SVG Viewer</header><item action="Open" id="Open">Open</item><item action="OpenNew" id="OpenNew">Open in New Window</item><separator/><item action="ZoomIn" id="ZoomIn">Zoom In^_^&E</item><item action="ZoomOut" id="ZoomOut">Zoom Out</item><item action="OriginalView" id="OriginalView">Original View</item><separator/><item action="Quality" id="Quality">Higher Quality</item><item action="Pause" id="Pause">Pause</item><item action="Mute" id="Mute">Mute</item><separator/><item action="Find" id="Find">Find...</item><item action="FindAgain" id="FindAgain">Find Again</item><separator/><item action="Copy" id="Copy">Copy Selected Text</item><item action="CopySVG" id="CopySVG">Copy SVG</item><item action="ViewSVG" id="ViewSVG">View SVG</item><item action="ViewSource" id="ViewSource">View Source</item><item action="SaveAs" id="SaveAs">Save SVG As...</item><separator/><item action="Help" id="Help">Help</item><item action="About" id="About">About Adobe SVG Viewer...</item></menu>


圖 2. 重構后的菜單





回頁首


5. 在Batik 下通過 java DOM 實現(xiàn) SVG 文檔操作

在 Batik 環(huán)境下還可以通過 Java 環(huán)境下的 DOM 接口直接操作當前視圖使用的 SVG 文檔。我們可以通過Batik 提供的 org.apache.batik.swing.JSVGCanvas 對象獲取當前顯示 SVG 文件的 DOM 文檔對象引用,通過對該 DOM 的操作改變當前 SVG 圖像的內(nèi)容:


JSVGCanvas svgCanvas = new JSVGCanvas();svgCanvas.setURI("dom.svg");SVGDocument svgDocument=svgCanvas.getSVGDocument();SVGSVGElement svgRoot=svgDocument.getRootElement() ;Element g5=svgDocument.getElementById("g5");g5.setAttribute("transform","translate(225, 250) ");Element shape=svgDocument.createElementNS("http://www.w3.org/2000/svg","circle");shape.setAttribute("cx", "100");shape.setAttribute("cy", "100");shape.setAttribute("r", "20");shape.setAttribute("style", "fill: green");g5.appendChild(shape);

需要重點提出來的是,在 Batik 中添加新的節(jié)點的時候,一定要指明添加節(jié)點的命名空間。另外需要特別注意的是,在 Batik 的 java 編程環(huán)境中,不支持對樣式如"shape.getStyle(). setProperty("stroke","red");"這樣的屬性設置,必須通過對 style 屬性的一次性賦值來設定元素的樣式。

你可以從參考資料中獲取 Batik 的詳細定義文檔。



參考資料

  • 有關 SVG 的背景知識,請閱讀 developerWorks 上的教程,"可伸縮向量圖形介紹"

  • 可以參考教程交互式動態(tài)可伸縮向量圖形

  • 通過 http://www.w3.org/TR/SVG11/ 獲取當前最新 SVG 標準文檔

  • Batik 項目介紹 http://xml.apache.org/batik/

  • 可以從http://www.adobe.com/svg/indepth/pdfs/CurrentSupport.pdf獲取 Adobo SVG Viewer3.0的技術細節(jié)

  • 可以通過http://www.w3.org/TR/DOM-Level-2-Core了解 DOM 對象的細節(jié)

  • 通過Sacré SVG你可以找到最近關于 SVG 的文章和新聞。


關于作者

?

陳珂 chenke@snmobile.com ,從業(yè)以來一直從事政府信息化建設和GIS的相關工作,自從多年前接觸SVG以來就對其產(chǎn)生極大的興趣。現(xiàn)在南京安元科技擔任技術總監(jiān)。您可以通過這里訪問我創(chuàng)建的基于SVG的GIS開源項目,我把它叫做AntGIS(小而強大)。


原文 :http://www-128.ibm.com/developerworks/cn/xml/x-svgscript/

轉載于:https://www.cnblogs.com/cuihongyu3503319/archive/2007/09/30/911458.html

總結

以上是生活随笔為你收集整理的使用脚本动态操作 SVG 文档的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。