x00 前言
在過去幾周中,F(xiàn)ortiGuard Labs一直在研究帶有SVG(Scalable Vector Graphics)圖像的Web應(yīng)用。根據(jù)研究結(jié)果,我們找到了Web應(yīng)用中的一些常見問題。在本文中,我們簡要介紹了SVG的特點(diǎn)以及針對SVG圖像的常見攻擊面。
根據(jù)之前的研究結(jié)果,我們梳理了一些常見的SVG攻擊方式,如下所示:
0x01 SVG簡介
SVG的全稱為 Scalable Vector Graphics(可縮放矢量圖),是一種基于XML的二維矢量圖格式,支持交互性及動畫展示。SVG圖像及具體行為由XML文本文件定義,可以通過任何文本編輯器以及繪圖軟件來創(chuàng)建并編輯。目前所有主流web瀏覽器都支持渲染SVG圖像。
來觀察一個示例,更好理解SVG圖像。如下圖所示,我們編寫了一些代碼來渲染SVG圖像:
圖1. simple.svg代碼片段
將該圖像保存為simple.svg,然后直接打開,或者將其包含在img/image/object/embed HTML標(biāo)簽中,如下圖所示:
圖2. 通過代碼渲染圖像
圖1代碼渲染生成的圖像如圖2所示,這是rect元素,瀏覽器會在x, y (100, 100)(即寬度和高度)位置渲染一個紅色矩形。
0x02 使用SVG的攻擊場景
雖然SVG提供了較大的靈活性,可以方便創(chuàng)建更多的動態(tài)web內(nèi)容,但同時也引入了一些安全風(fēng)險(xiǎn)。在下文中,我們將討論一些常見的攻擊向量,我們在互聯(lián)網(wǎng)上的一些主流站點(diǎn)上都觀察到過這些攻擊方式。
跨站腳本
我們可以通過腳本方式來訪問并修改SVG文檔的任何內(nèi)容,這與HTML操作方式類似。默認(rèn)的腳本語言為ECMAScript(與JavaScript密切相關(guān)),每個SVG元素及屬性都對應(yīng)已定義的DOM(Document Object Model,文檔對象模型)對象。相關(guān)腳本被封裝在<script>元素中。
這意味著如果web服務(wù)器允許用戶上傳任意SVG圖像,就存在XSS(跨站腳本)安全風(fēng)險(xiǎn)。如下所示,我們將腳本存放在圖像中:
圖3. xss.svg代碼片段
將該圖像保存為xss.svg,然后直接打開,如下圖所示:
圖4. 直接訪問該文件觸發(fā)XSS
如果將該文件鏈接到某個HTML頁面,訪問該頁面也可以觸發(fā),如下圖所示:
圖5. 通過鏈接文件觸發(fā)XSS
JavaScript代碼會在瀏覽器上下文中執(zhí)行,這意味著攻擊者可以使用該文件執(zhí)行惡意行為,比如竊取用戶隱私信息等。
HTML注入
在某些情況下,XSS payload會被服務(wù)端過濾,然而我們依然能夠通過SVG圖像的特定功能來注入HTML代碼。如前文所述,SVG是基于XML的一種矢量圖,因此我們無法簡單將HTML內(nèi)容放入其中,不然會破壞XML的語法。
為了避免這種情況,SVG提供了一個foreignObject元素,可以用來包含來自其他XML命名空間的元素。在瀏覽器上下文中,這部分?jǐn)?shù)據(jù)很可能采用(X)HTML形式。
來看一下html.svg圖像:
圖6. html.svg代碼片段
當(dāng)我們在foreignObject內(nèi)添加一個body標(biāo)簽以及XHTML命名空間時,可以使用xmlns屬性來聲明命名空間。采用這種方式,瀏覽器會將body標(biāo)簽及其所有子標(biāo)簽解析為屬于XHTML的元素。因此,我們可以將來自SVG的任意XHTML代碼渲染到頁面中:
圖7. HTML注入漏洞
這種方式可以運(yùn)行任意HTML代碼,意味著我們可以簡單從SVG圖像中發(fā)起類似釣魚、繞過同源策略、CSRF之類的攻擊。
XML實(shí)體:Billion Laughs Attack
由于SVG是基于XML的矢量圖,因此可以支持Entity(實(shí)體)功能。Entity可以用來定義特殊字符的快捷方式,也可以聲明成內(nèi)部或外部實(shí)體。
我們可以通過如下方式聲明內(nèi)部Entity:
<!ENTITY entity-name "entity-value">
通過如下方式聲明外部Entity:
<!ENTITY entity-name SYSTEM "URI/URL">
如果解析文件的XML解析器存在脆弱性,那么我們就可以濫用外部Entity功能來泄露內(nèi)部數(shù)據(jù)。由于現(xiàn)在大家主要使用的都是現(xiàn)代瀏覽器,因此我們假設(shè)可用的解析器都經(jīng)過fuzzer的嚴(yán)格測試,因此沒那么容易被攻擊。在這個前提下,這里我們主要討論如何濫用內(nèi)部Entity。
entity.svg的內(nèi)部實(shí)現(xiàn)如下所示:
圖8. entity.svg代碼片段
如上圖所示,我們在第2行定義lab這個Entity,然后在SVG元素中調(diào)用該實(shí)體。結(jié)果如圖9所示:
圖9. lab實(shí)體被加載到頁面
一切非常順利,來嘗試另一個例子:entity_2.svg,如下圖所示:
圖10. entity_2.svg代碼片段
結(jié)果如下:
圖11. lab2實(shí)體被加載到頁面
如上圖所示,這里的文本內(nèi)容被重復(fù)渲染,這表明我們可以使用Entity標(biāo)簽發(fā)起“ Billion Laughs ”攻擊。
“ Billion Laughs ”攻擊是一種DoS(拒絕服務(wù))攻擊,目標(biāo)是XML文檔解析器。這種攻擊也被稱之為XML炸彈或者指數(shù)實(shí)體攻擊。
圖12. billion_laughs.svg代碼片段
我們的瀏覽器在解析這個 billion_laughs.svg數(shù)據(jù)時,只花了4~5秒就能正常響應(yīng)。這是因?yàn)榇蠖鄶?shù)現(xiàn)代瀏覽器已經(jīng)能夠能應(yīng)付這種攻擊,可以在渲染過程中解決該問題,因此不會造成安全風(fēng)險(xiǎn)。
拒絕服務(wù):新型SVG “Billion Laughs”攻擊
在上一節(jié)中,我們發(fā)現(xiàn)“ Billion Laughs ”攻擊可以延緩瀏覽器的處理速度,瀏覽器需要4~5秒才能應(yīng)付該攻擊。不幸的是,攻擊者還可以通過SVG圖像,發(fā)起另一種“ Billion Laughs ”攻擊,繞過這些防御措施。
這一次我們使用xlink:href來代替XML Entity。來看一下 xlink_laughs.svg所使用的payload:
圖13. xlink_laughs.svg代碼片段
xlink:href屬性以IRI(國際資源標(biāo)識)方式定義了對某個資源的引用,該鏈接的具體含義需根據(jù)使用該鏈接的每個元素的上下文來決定。
<use>元素從SVG文檔中獲取節(jié)點(diǎn),然后將其復(fù)制到其他位置。
我們現(xiàn)在a0中定義circle元素,然后在a1、a2、a3……中通過xlink:href屬性調(diào)用<use>元素,通過這種方式反復(fù)克隆circle。結(jié)果如下圖所示:
圖14. 在解析惡意SVG時,通過xlink:href發(fā)起“ Billion Laugh”攻擊
需要注意的是,在最壞的情況下,大多數(shù)現(xiàn)代瀏覽器在嘗試解析網(wǎng)站上的這張SVG圖像時可能會發(fā)生崩潰,或者至少會出現(xiàn)無響應(yīng)情況。
有趣的是,我們在測試某些開源SVG/XML過濾器時,發(fā)現(xiàn)這些過濾器并不能正確捕捉到圖13所示的SVG圖像。因此,這種錯誤格式的SVG圖像也可能造成DoS效果。
0x03 總結(jié)
SVG圖像更像HTML,而不單單是一張簡單的圖像。因此,我們建議web開發(fā)者盡可能不要以對象或者iframe形式加載任何SVG。Web管理員同樣應(yīng)當(dāng)限制可以上傳到站點(diǎn)的文件類型。
此外,任何不可信的SVG圖像在被上傳到服務(wù)端前都必須經(jīng)過過濾處理,可以采取如下操作:
我們使用一些瀏覽器來直接打開這些惡意SVG文件,對比結(jié)果如下圖所示:
大家可以訪問我們的Github倉庫下載本文使用的SVG樣本。
0x04 參考資料
[1] W3C, “Scalable Vector Graphics” https://www.w3.org/TR/SVG2/ (02 September, 2019)
[2] OWASP, “The Image that called me” https://www.owasp.org/images/0/03/Mario_Heiderich_OWASP_Sweden_The_image_that_called_me.pdf (02 September, 2019)
[3] Blackhat, “Exploiting Browsers without Image Parsing Bugs” https://www.blackhat.com/docs/us-14/materials/us-14-DeGraaf-SVG-Exploiting-Browsers-Without-Image-Parsing-Bugs.pdf (02 September, 2019)
原文鏈接:https://www.anquanke.com/post/id/190651
我們閱讀這篇文章之前,我們需要思考下,我們?yōu)槭惨チ私釹VG,閱讀了這篇文章是否可以給我們帶來幫助。
1. 如果你想要一張 css或者JavaScript可以控制的圖片,那么你可以考慮SVG。
2. 如果你期望圖片的質(zhì)量不會因?yàn)榉糯蠡蚩s小而降低,那么你可以考慮SVG。
3. 如果你期望網(wǎng)頁對殘障人士和視力受損的用戶有更好的體驗(yàn),那么你可以考慮SVG。
4. 如果你期望圖片在高清設(shè)備還是低分辨率設(shè)備上,都能保持清晰和細(xì)膩的圖像質(zhì)量,那么你可以考慮SVG。
我們在學(xué)習(xí)SVG之前,需要先了解一下位圖和矢量圖。
簡單來說:
詳細(xì)來說:
SVG究竟什么?
是Scalable Vector Graphics的縮寫,意思是可縮放矢量圖形。
這是一種基于XML的二維矢量圖形標(biāo)準(zhǔn),由W3C開發(fā)的。
對于初學(xué)者來說,可以將SVG理解為一套新的HTML標(biāo)簽。
所以我們可以使用css和JavaScript來對標(biāo)簽進(jìn)行操作。
很多小伙伴可能已經(jīng)忘記了XML,我們回顧一下:
XML(可擴(kuò)展標(biāo)記語言)是一種用于描述數(shù)據(jù)的標(biāo)記語言,它使用一系列簡單的標(biāo)記來描述數(shù)據(jù),這些標(biāo)記可以用來表示不同類型的數(shù)據(jù)元素,如標(biāo)題,作者,價(jià)格等。
SVG的優(yōu)勢:
SVG的劣勢:
設(shè)計(jì)復(fù)雜性:SVG需要具備一定的設(shè)計(jì)和制作技巧,與位圖相比,SVG的設(shè)計(jì)難度較大,需要更高的技術(shù)水平。
瀏覽器兼容性:在一些舊版瀏覽器中,可能存在對SVG的兼容性問題。
渲染速度:SVG復(fù)雜度過高會降低頁面渲染速度。
對于前端開發(fā)的我們,要如何去使用SVG呢?
SVG歸根結(jié)底來說和JPG,PNG一樣,也是一種圖像格式,所以我們可以在HTML中,將SVG的路徑設(shè)置為<img>的src屬性。
我們也可以將SVG的代碼放在HTML中,我們完全可以把SVG的代碼看做成我們的HTML標(biāo)簽。
例如:
<svg width="500" height="500">
<circle cx="100" cy="100" r="50" fill="transparent" stroke="#000"></circle>
</svg>
我們也可以通過css的background-image或者偽元素,將SVG圖片作為背景圖像。
總的來說,任何需要保持清晰度,動態(tài)交互和無損縮放的圖形場景,都可以考慮使用SVG。
Canvas和SVG都是用于在網(wǎng)頁上繪制圖形的工具,但它們在許多方面都存在顯著的差異。以下是對Canvas和SVG的對比:
總結(jié):Canvas和SVG各有其優(yōu)勢和適用場景。Canvas更適合圖像密集型的游戲和需要高效渲染的應(yīng)用,而SVG更適合處理矢量圖形和大型渲染區(qū)域。
說了這么多,我們來開始實(shí)戰(zhàn),我們要在HTML中,畫出一個SVG圖像。
<html>
<body>
<h1>Feng SVG</h1>
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="4" fill="yellow" />
<circle cx="150" cy="100" r="80" fill="green" />
<text x="150" y="115" font-size="16" text-anchor="middle" fill="white">RUNOOB SVG TEST</text>
</svg>
</body>
</html>
運(yùn)行后:
代碼解讀:
我們還可以在線設(shè)計(jì)SVG圖片,我們可以直接使用該圖片或者拷貝其代碼復(fù)制到我們的代碼中。
SVG在線編輯: c.runoob.com/more/svgedi…
示例一:
正常的矩形
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="300" height="100" style="fill:rgb(122,122,0);stroke-width:2;stroke:rgb(0,0,0)" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在SVG圖像中繪制一個寬度為300像素、高度為100像素、填充顏色為黃色調(diào)、線條寬度為2像素、線條顏色為黑色的矩形。
示例二:
填充和邊框的透明度
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect x="50" y="20" width="150" height="150" style="fill:blue;stroke:red;stroke-width:5;fill-opacity:0.5;stroke-opacity:0.5" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個SVG圖像中繪制一個左上角坐標(biāo)為(50, 20)、寬度為150像素、高度為150像素、填充顏色為藍(lán)色、線條顏色為紅色、線條寬度為5像素、填充透明度和線條透明度都為0.5的矩形。
示例三:
整個元素的透明度
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="500px">
<rect x="50" y="20" width="150" height="150" style="fill:blue;stroke:pink;stroke-width:5;opacity:0.4" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個500x500像素的SVG圖像中繪制一個左上角坐標(biāo)為(50, 20)、寬度為150像素、高度為150像素、填充顏色為藍(lán)色、線條顏色為粉紅色、線條寬度為5像素、透明度為0.4的矩形。
示例四:
圓角矩形
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="500px">
<rect x="50" y="20" rx="20" ry="20" width="150" height="160" style="fill:red;stroke:black;stroke-width:1;opacity:0.5" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個500x500像素的SVG圖像中繪制一個左上角坐標(biāo)為(50, 20)、寬度為150像素、高度為160像素、填充顏色為紅色、線條顏色為黑色、線條寬度為1像素、透明度為0.5的圓角矩形。
示例:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="red" stroke-width="2" fill="blue" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個SVG圖像中繪制一個圓心坐標(biāo)為(100, 50)、半徑為40像素、邊框顏色為紅色、邊框?qū)挾葹?像素、填充顏色為藍(lán)色的圓形。
示例:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500">
<ellipse cx="300" cy="80" rx="100" ry="50" style="fill:red;stroke:purple;stroke-width:2" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個500x500像素的SVG圖像中繪制一個中心點(diǎn)坐標(biāo)為(300, 80)、長軸半徑為100像素、短軸半徑為50像素的紅色橢圓,線條顏色為紫色,線條寬度為2像素。
示例:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<line x1="0" y1="0" x2="200" y2="200" style="stroke:black;stroke-width:5" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個SVG圖像中繪制一條從(0, 0)到(200, 200)的黑色線段,線條寬度為5像素。
示例一:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<polyline points="20,20 40,25 60,40 80,10 120,140 200,180" style="fill:none;stroke:black;stroke-width:3" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個SVG圖像中繪制一個黑色的折線。這個折線有6個點(diǎn),形狀大致為一個不規(guī)則的六邊折線。注意:因?yàn)樵O(shè)置了fill:none,所以該多邊形線段不會進(jìn)行填充,只顯示其黑色邊框。
示例二:
畫一個五角星
<svg style="height:300px;width:300px;" xmlns="http://www.w3.org/2000/svg" version="1.1">
<polyline points="100 10,40 180,190 60,10 60,160 180" style="fill:blue;stroke:blue;stroke-width:1" />
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個300x300像素的區(qū)域內(nèi)繪制一個藍(lán)色的多邊形。這個多邊形有5個頂點(diǎn),形狀大致為一個不規(guī)則的五邊形。
示例一:
<svg height="210" width="500">
<polygon points="200,10 250,190 160,210"
style="fill:red;stroke:purple;stroke-width:1"/>
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個500x210像素的SVG圖像中繪制一個由三個頂點(diǎn)定義的多邊形,填充顏色為紅色,線條顏色為紫色,線條寬度為1像素。
示例二:
畫一個五角星
<svg style="height:300px;width:300px;" xmlns="http://www.w3.org/2000/svg" version="1.1">
<polygon points="100 10,40 180,190 60,10 60,160 180" style="fill:none;stroke:black;stroke-width:5"/>
</svg>
效果:
代碼解析:
綜上,這段代碼會在一個300x300像素的SVG圖像中繪制一個由七個頂點(diǎn)定義的多邊形,沒有填充顏色,線條顏色為黑色,線條寬度為5像素。
路徑數(shù)據(jù):
示例:
畫一個三角形
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<path d="M150 0 L75 200 L205 270 Z" />
</svg>
效果:
代碼解析:
綜上,這段代碼將在SVG圖像中繪制一個由三個直線段組成的封閉圖形,其頂點(diǎn)坐標(biāo)分別為(150, 0),(75, 200)和(205, 270)。
直接在元素屬性上設(shè)置樣式,比如將矩形填充色改成粉紅
<svg width="400" height="400" style="border: 1px solid red;">
<rect
x="100"
y="100"
width="200"
height="100"
fill="pink"
/>
</svg>
把所有樣式寫在 style 屬性里
<svg width="400" height="400" style="border: 1px solid red;">
<rect
x="100"
y="100"
width="200"
height="100"
style="fill: pink;"
/>
</svg>
將樣式寫在 <style> 標(biāo)簽里
<style>
.rect {
fill: pink;
}
</style>
<svg width="400" height="400" style="border: 1px solid red;">
<rect
x="100"
y="100"
width="200"
height="100"
class="rect"
/>
</svg>
將樣式寫在 .css 文件里,然后在頁面中引入該 CSS 文件。
SVG動畫可以通過多種方式實(shí)現(xiàn),包括使用SMIL、CSS和JavaScript。
能讓SVG不靠JavaScript與CSS就能動起來是因?yàn)槭褂昧薙MIL(Synchronized Multimedia Integration Language),是W3C的標(biāo)準(zhǔn)之一,旨在以XML格式提供多媒體的交互表現(xiàn)(白話點(diǎn)其實(shí)就是動畫),是Web上動畫的開路先鋒,啟發(fā)了Web animation與CSS animation。SVG與SMIL的開發(fā)團(tuán)隊(duì)合作,讓SVG能利用SMIL達(dá)到如下效果:
光是這些特性就夠我們組合出很多種的動畫了, 使用方法也不難,只要在SVG元素內(nèi)置入以下四種元素即可操作動畫:
例如:
<circle cx=“56.7573”cy=“92.8179”r=“2”fill=“black”stroke=“black”stroke-width=“1”>
<set attributeName=“cy”to=“105.7318”begin=“2s”/>
</circle>
代碼解析:
這段代碼用于描述一個圓形,并在特定時間改變其中心點(diǎn)的y坐標(biāo)。
綜上,這段代碼繪制了一個半徑為2單位、填充和邊框顏色均為黑色的圓形,并設(shè)置了一個動畫,使圓心的y坐標(biāo)在2秒后從92.8179變?yōu)?05.7318。
通過設(shè)置一組 CSS 樣式和關(guān)鍵幀,可以實(shí)現(xiàn)基于時間或基于事件的 SVG 動畫。這種方式實(shí)現(xiàn)的 SVG 動畫相對簡單,具有易于實(shí)現(xiàn)、可讀性好、易于維護(hù)、性能良好等優(yōu)點(diǎn)。
下面是一個基于 CSS 的 SVG 動畫示例,實(shí)現(xiàn)了一個圓形的旋轉(zhuǎn)動畫:
<svg>
<circle cx="50" cy="50" r="40" />
</svg>
<style>
circle {
fill: red;
animation: rotate 2s linear infinite;
}
@keyframes rotate {
to {
transform: rotate(360deg);
}
}
</style>
通過 JavaScript,可以對 SVG 圖形進(jìn)行更加自由和復(fù)雜的動畫操作。JavaScript 可以對 SVG 元素的各種屬性,如位置、大小、顏色、透明度、路徑等進(jìn)行操作,配合定時器和事件監(jiān)聽等方法,實(shí)現(xiàn)豐富多彩的 SVG動畫。
下面是一個基于 JavaScript 的 SVG 動畫示例,實(shí)現(xiàn)了一個小球自由落體,碰撞彈跳的效果:
<svg>
<circle id="ball" cx="50" cy="50" r="20" />
</svg>
<script>
let ball=document.querySelector("#ball");
let startPos=50;
let endPos=200;
let speed=3; // 設(shè)置球下落速度
let gravity=0.2; // 設(shè)置加速度
function moveBall() {
let pos=parseFloat(ball.getAttribute("cy"));
let vel=parseFloat(ball.getAttribute("data-vel")) || 0;
// 計(jì)算球的速度和位置
vel +=gravity;
pos +=vel * speed;
// 碰撞檢測
if (pos + 20 > endPos) {
pos=endPos - 20;
vel=-vel * 0.8;
}
// 更新球的位置和速度
ball.setAttribute("cy", pos);
ball.setAttribute("data-vel", vel);
// 循環(huán)移動球
if (pos < endPos - 20) {
window.requestAnimationFrame(moveBall);
}
}
moveBall();
</script>
總的來說,SVG是一種強(qiáng)大的圖形描述語言,具有可縮放性、交互性、可訪問性、靈活性和跨平臺兼容性等特點(diǎn)和優(yōu)勢。它可以用于創(chuàng)建各種復(fù)雜的二維矢量圖形和富交互的Web應(yīng)用,為Web設(shè)計(jì)和開發(fā)提供了更多的可能性。
隨著Web技術(shù)的不斷發(fā)展,相信SVG的應(yīng)用范圍還將不斷擴(kuò)大。
原文鏈接:https://juejin.cn/post/7322344486159106100
下這個例子顯示了,在html中單擊命令按鈕設(shè)定svg中的矩形的填充顏色,并且調(diào)用svg的js函數(shù)FunCallByHtmlJs,產(chǎn)生個消息框。
在svg中,單擊矩形時,設(shè)置html中的text的文本內(nèi)容,并且調(diào)用html的js函數(shù)FunCallBySvgJs,產(chǎn)生個消息框。
svg文檔以嵌入在html文檔中運(yùn)行。
例子在IE 6.0 + Adobe SVG Viewer 3.03中文版下測試通過。
svg文件的代碼:
//文件名:Svg&HtmlInteractive.svg
<svg width="640" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="100%" onload="init(evt)" onclick="Click(evt)">
<script type="text/javascript">
var svgDoc=null ;
var svgRoot=null ;
var parentWnd=null ; //保存html的window對象
//初始化
function init(evt)
{
svgDoc=evt.target.ownerDocument ;
svgRoot=svgDoc.documentElement ; //在html中的第二種交互方式會用到
parentWnd=window.parent ; //ASV 3.0可以這么寫。英文6.0版的要換種寫法
if(parentWnd.document.title==null || parentWnd.document.title=='')
{
alert("請不要直接在瀏覽器中打開'svg'文檔!");
//下面的代碼作用是不提示確認(rèn)關(guān)閉窗口
parentWnd.opener=null ;
parentWnd.open('', '_self') ;
parentWnd.close() ;
}
svgDoc.svgWnd=window ; //這里人為進(jìn)行設(shè)定,以便在html中的第一種交互方式中可以取的到svg的window對象
}
function FunCallByHtmlJs()
{
alert('這個消息框是在html的js中調(diào)用svg的js函數(shù)產(chǎn)生的。') ;
}
function Click(evt)
{
var id=evt.target.id ;
if(id=='rect') //單擊在矩形上,而不是背景上時
{
if(parentWnd)
{
parentWnd.txt.value='在svg中設(shè)置html中的text的文本內(nèi)容' ;
parentWnd.FunCallBySvgJs() ; //調(diào)用html中的js函數(shù)
}
}
}
</script>
<rect id="background" x="0" y="0" width="100%" height="100%" fill="gray" />
<rect id="rect" x="50" y="50" width="100" height="100" fill="green" />
<text font-family="SimSun" font-size="14" fill="yellow" x="50" y="50" id="text">單擊svg的矩形,設(shè)置html的text文本內(nèi)容</text>
</svg>
html文件的代碼:
//文件名:Svg&HtmlInteractive.html
<html>
<head>
<title>SVG與html的交互</title>
</head>
<body onload="htmInit()">
<script type=text/javascript>
var svgDoc=null;
var svgRoot=null;
var svgWnd=null; //svg的window對象
function htmInit()
{
txt.value='';
}
function FunCallBySvgJs()
{
alert('這個消息框是在svg的js中調(diào)用html的js函數(shù)產(chǎn)生的。');
}
function Btn1Clk()
{
//第一種方式
svgDoc=emSvg.getSVGDocument();
if (svgDoc==null) return;
svgRoot=svgDoc.documentElement;
if (svgRoot==null) return;
var rect=svgRoot.getElementById('rect');
if(rect) rect.setAttribute('fill', 'blue');
svgWnd=svgDoc.svgWnd ; //這個window對象是在svg的初始化里面添加進(jìn)去的
if (svgWnd) svgWnd.FunCallByHtmlJs(); //調(diào)用svg里的js函數(shù)
}
function Btn2Clk()
{
//第二種方式
svgWnd=emSvg.window;
if(svgWnd==null) return;
svgRoot=svgWnd.svgRoot; //svgRoot在svg的js中是個全局的變量
if(svgRoot==null) return;
var rect=svgRoot.getElementById('rect');
if(rect) rect.setAttribute('fill', 'red');
svgWnd.FunCallByHtmlJs(); //調(diào)用svg里的js函數(shù)
}
</script>
<input type="button" value="設(shè)置svg中矩形的填充顏色為藍(lán)色" onclick="Btn1Clk()" />
<input type="button" value="設(shè)置svg中矩形的填充顏色為紅色" onclick="Btn2Clk()" />
<input id="txt" type="text" value="" />
<embed id="emSvg" runat="server" src="http://zg672313.blog.163.com/blog/SvgHtmlInteractive.svg" mce_src="http://zg672313.blog.163.com/blog/SvgHtmlInteractive.svg" width="100%" height="95%" wmode="transparent"/>
</body>
</html>
效果圖:
另外: 在aspx 頁面中,emSvg對象會找不會,應(yīng)該使用 document.getElementById("emSvg") 來查找 SVG對象
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。