Web开发中的矢量绘图(vml,svg)处理和应用
為什么80%的碼農都做不了架構師?>>> ??
前言
1991 年物理學家?Tim Berners-Lee?首次在因特網上發布了 HTML 的第一版描述規范文檔。經過了 20 多年的發展,HTML 語言成為如今編程最為廣泛的語言和互聯網上采用最廣的文檔格式。雖然 HTML 發展十分迅速并具有諸多優點,但其始終不能提供一個良好的矢量繪圖解決方案。很多應用為獲得絢麗的動畫和繪圖效果,不得已在頁面中嵌入大量的 Flash。這不僅降低了頁面元素的交互性,大量的 Flash 同時嚴重影像了頁面性能,更加頭疼的是 Flash 內容不能被搜索引擎搜索。雖然有良好的跨瀏覽器特性,但是用戶不得不安裝一個瀏覽器插件。
本文首先針對不同瀏覽器詳細闡述不同的矢量繪圖解決方案,其中包括 HTML5 Canvas、SVG 以及 VML 等技術;之后針對每種不同的技術介紹其實現和使用方法;最后本文將介紹如何創建一個跨瀏覽器的矢量繪圖應用,并對當前的一些快瀏覽器矢量繪圖框架進行簡單介紹。
?
?
VML
VML ( Vector Markup Language ) 矢量可標記語言是一種基于 XML 語法的矢量繪圖語言。1998 年由?Autodesk?,Hewlett-Packard,Macromedia?,Microsoft?幾家公司共同向 W3C 提交,并希望能夠成為矢量繪圖的國際化標準。雖然 VML 最終沒有成為 W3C 推薦的矢量繪圖標準,但其還是被大量應用于 MS Office、Visio 等軟件和 IE 瀏覽器中。由于 Office 和 IE 的成功和其廣闊的市場占有率,VML 已經成為在 IE 中首選的矢量繪圖語言。
由于 VML 基于 XML 標準的矢量繪圖語言,VML 先天性的具有表示方法簡單、易于擴展等優勢。簡單的一行標記代碼就可以使開發人員快速繪制輸出線段、圓形、矩形、圓矩形、曲線、多邊形、弧型等矢量圖形。并且可以通過修飾這些原色的邊框、陰影、填充、背景、漸變、箭頭等等來增強和提升其外觀效果。同時由于 VML 與 HTML 兼容,可以將 VML 與 HTML 混合在一起使用。VML 所繪制的每一個圖形,都跟 HTML 元素一樣是一個圖形對象,同樣支持 DHTML 對象編程模型、DHTML 事件編程模型。因此開發人員可以利用 JavaScript 等腳本輕松的讀取、更改 VML 圖形對象的各種屬性,響應用戶觸發的鼠標、鍵盤等事件,實現與用戶交互。如果有機的配合定時器和一些其他模型,則能實現類似 Flash 般復雜的動畫,輸出高質量質量動畫效果。
VML 的使用非常簡單,它采用 HTML 的標簽方式來定義和繪制圖像。例如下面的代碼所示:
清單 1.VML 代碼示例
如清單 1 所示,上面代碼是一段簡單的 VML 示例代碼,繪制出一個藍色的橢圓形。其中 xmlns 標記的全稱是 XML NameSpace,用來指定該文檔的命名空間。 Behavior 是 IE5.0 版本以后推出的一個非常強大功能。通常情況下 Behavior 與樣式表結合一起使用,給任何 HTML 對象增加新的行為,例如新的屬性、方法、事件等等。在上面的示例代碼中,Behavior 的用處是把命名空間“v”和系統預定義的行為 VML 連接起來,提供系統默認的 VML 功能。v:oval 標簽則定義一個橢圓形的 VML 圖形,fillcolor 屬性指定該圖形用藍色來填充。
圖 1. 清單 1 示例代碼效果圖
?
VML 默認定義了許多圖形元素,包括:Shape 基本抽象形狀,它在 VML 中代表任何形狀;Line 直線或者線段;Polyline 代表特殊的線段,它將 Points 屬性所指定的一系列的點連接起來;Rect 代表矩形對象,它在流程圖的繪制中非常常用;Roundrect 顧名思義為圓角矩形,它的功能和矩形對象基本上同;Oval 是 VML 中的圓形對象,你可以定義它的寬度和高度來得到不同的橢圓形狀,還可以通過指定 arc 弧屬性來繪制一個圓上一段弧度,利用 Oval 對象我們可以繪制出各種我們想要的曲線;Group 是 VML 中的一個容器標簽,它的使用很簡單,但功能很強大。它能讓一系列的 VML 對象使用共同的坐標系和縮放尺度,這樣改變 CoordSize 值可以使得這一組圖形的坐標和縮放尺度一起改變。Group 經常被用來實現一組適量圖形的動態放大和縮小。
VML 看似簡單的標簽和屬性卻定義了很多功能強大的組件。將這些圖形標簽組合在一起使用可以繪制出很多漂亮、復雜甚至是令人難以想象的畫面,例如下圖就是一個利用 VML 繪制出的《蒙娜麗莎》畫像。如果在于 JavaScript 等腳本混合使用,可以繪制出和 Flash 一樣絢麗的動畫和游戲效果。
圖 2. VML 在 IE 瀏覽器中繪制出的《蒙娜麗莎》畫像
?
?
?
SVG
SVG 是可擴展矢量圖(Scalable Vector Graphics)的簡稱,它是 W3C 組織為適應因特網的飛速發展而制定的一套基于 XML 語言的二維矢量圖形的語言描述規范。W3C 中的 SVG 開發工作組的的成員包括了 IBM、Adobe、Apple、Microsoft、AutoDesk 等一批知名廠商,使其成為了通用的標準。而且隨著移動通訊的迅猛發展,W3C 又推出了 SVG 的移動版本,并被多個移動設備廠商的多個型號的手機所支持,并成為 3G 時代的一個重要的技術標準。在 PC 平臺上,由于 SVG 常用于豐富 Web 頁面內容,一部分瀏覽器已經提供了對 SVG 格式的一些支持,如 Firefox、Safari 等,而 IE 系列瀏覽器中的 IE6,、IE7 和 IE8 都沒有對 SVG 提供支持。但微軟顯然已經意識到 SVG 標準的已經變得越來越普及,所以不但加入了 W3C 下面的 SVG 工作小組,更是在已經發布的 IE9 的 Beta 版中提供了對 SVG 基本特性的支持。值得注意的是,雖然很多瀏覽器甚至微軟的 IE9 都已經對 SVG 提供一定的支持,但是其中不少只是支持 SVG 標準的部分功能,如果想讓這些瀏覽器全面支持 SVG 標準,需要安裝一些 SVG 的瀏覽插件,比如 Adobe SVG Viewer。借助這些 SVG 插件,瀏覽器上可支持絕大部分現有 SVG 規范中的內容,這里說“絕大部分”是因為 SVG 至今仍然是一個發展的標準,現在和將來的都會有一些新的變化,這些 SVG 瀏覽插件只會支持在某個穩定版本下的確定的功能。當前 SVG 的穩定版本是 W3C 于 2003 年 1 月份發布的 SVG1.1,后續版本 SVG1.2 正在研究制定的過程中。
SVG 遵循 XML 格式的描述語言來描述矢量圖形的內容,支持三種矢量顯示對象,包括矢量圖形對象(矩形、圓,曲線等)、嵌入式外部對象(PNG、JPEG、SVG 等)和文字對象。SVG 最終的文件格式是文本,對開發人員來說具有良好的可讀性和可擴展性。平均來講,SVG 文件的大小要小于 JPEG 等其他的網絡圖形格式,而且 SVG 支持利用 gzip 壓縮算法進行壓縮從而獲得很大的壓縮比,壓縮后生成的文件格式為 SVGZ。因為 SVG 中的矢量顯示對象是被描述出來的,所以支持無損的放大縮小,而對于那些柵格圖形格式,如 BMP,JPEG 等,放大或是縮小需要利用數值算法進行插值而造成失真。SVG 圖形格式支持文字對象,可以很方便的建立文字索引,進而實現基于內容的圖像搜索。SVG 格式支持多種濾鏡和特殊效果,如給文字內容加上陰影。此外,最重要的一點是 SVG 具有良好的動態性,一方面自身的有基于 SMIL(Synchronized Multimedia Integration Language,同步多媒體集成語言)標準的動態內容;另一方面可以利用 JavaScript 腳本來控制對象,來提供良好的互動。SVG 的這些特性使其得到了廣泛的支持和應用。
SVG 通過多種標簽元素來構成整個的矢量圖形,包括根元素 svg,圖形對象:rect(矩形)、circle(圓)、ellipse(橢圓)、line(線)、polygon(多邊形)、polyline(多直線圖形)、path(路徑生成圖形)等。濾鏡效果:feBlend、feColorMatrix、feComponentTransfer、feComposite、feConvolveMatrix 等,漸變效果:線性漸變和徑向漸變。SVG 文檔一般是以獨立的文件存在的,并且以 .svg 作為擴展名,如果是 GZIP 壓縮過的文件則以 .svgz 作為擴展名。下面的清單 2 是一個 SVG 靜態圖形文件的例子,其中先是定義了一個高斯濾鏡的效果和一個線性梯度的效果,隨后定義了一個正方形和一個橢圓,將已定義線性梯度應用于前者,高斯濾鏡應用于后者。將清單 2 中的內容保存到一個文本文件并以 svg 作為擴展名,用 1.5 以上版本的 Firefox 瀏覽器打開,就會看到圖 3 中所示的內容。
清單 2. SVG 靜態圖形的文件
圖 3. SVG 靜態圖形在 Firefox 瀏覽器中的展現
?
上面的例子是用 Firefox 直接打開 SVG 文檔文件來瀏覽,但是在一般的 Web 應用中,更多的情況是將 SVG 文檔嵌入到 HTML 頁面中,在瀏覽器渲染頁面的時候直接將 SVG 的圖像渲染到展現頁面上。將 SVG 圖形嵌入 HTML 頁有四種方式:通過 object 標簽,通過 embed 標簽,通過 iframe 標簽和直接將 SVG 的內容嵌入到頁面中。然而,現在支持 SVG 的主流的瀏覽器包括 Firefox、Safari 等不支持將 SVG 內容直接嵌入的方式,對另外三種方式基本能夠支持。清單 3 給出了利用 object 標簽、embed 標簽和 iframe 標簽將上面的 SVG 文檔嵌入 HTML 頁面的例子。圖 4 給出了這個 HTML 文檔在 Firefox 上的展現結果。
清單 3. 嵌入 SVG 文檔的 HTML 頁面
圖 4. Firefox 打開的嵌入 SVG 文檔的 HTML 頁面
?
SVG 支持的動態特性既包括 SVG 圖像自身的動畫也包括 SVG 圖像的各種交互功能。SVG 的動畫是 SVG 規范中的特性,使用不同的標簽元素來聲明,它們中有一部分是在 SMIL 定義的,如 animate、set、animateMotion 和 animateColor,剩下的則是 SVG 標準擴展的,如 animateTransform。另外,SVG 還為 animateMotion 標簽元素添加了三個屬性:path、keyPoints、rotate,以及一個子標簽元素 mpath。在下面的例子中,我們將用 animate 和 set 來實現一些效果。animate 允許一個圖形元素的某個屬性的值在一段時間內等量的變化,而 set 則是在一段時間內將值賦給某個屬性,具體如清單 4 中的代碼所示。由于 Firefox3. 版本不支持 SVG 的動畫,所以這段文檔中動畫需要用其他支持 SVG 動畫的瀏覽器如 Safari 或是安裝 SVG Viewer 才可瀏覽。
清單 4. 加入動畫效果的 SVG 文檔
SVG 圖像的交互包括 SVG 中的鏈接、事件響應以及腳本支持。SVG 中的每一個圖形對象都可以包裝在不同的鏈接標簽里面。與 HTML 中的鏈接的標簽相同,SVG 也使用 <a> 來表示鏈接,將其與一個 xlink:href 屬性結合就可以建立一個鏈接。<a> 和 </a> 標簽之間的所有內容作為鏈接點。SVG 標準支持鼠標和鍵盤事件,可以在 XML 描述文檔中直接定義對這些事件的監聽和響應,這些響應一般是某個動畫設定,通過上文提到的 set、animate 等來實現。雖然通過 SVG 的 XML 元素已經可以實現一定的動畫效果和事件響應,但如果想要實現更復雜的邏輯就需要腳本的支持。SVG 支持通過 JavaScript 腳本訪問 SVG 文檔構成的 DOM 節點樹,查詢、修改 DOM 節點的屬性,調用其公開的方法,監聽其發布的事件。JavaScript 腳本可以通過 script 元素直接嵌入到 SVG 文檔中或是通過 script 的 xlink:href 來從外部腳本文件引入。清單 5 中給出的例子是在清單 4 的基礎上加入了些 JavaScript 腳本,實現了對原正方形的矢量圖形的鼠標單擊事件的響應。這個事件處理的函數中進行了一些節點添加和刪除的操作:將包含“IBM”文本的 Text 節點刪掉,創建了一個包含“BTT”文本的 Text 節點并添加到 SVG 的 DOM 樹中。
清單 5. 加入 JavaScript 腳本的 SVG 文檔
在本小節中,我們介紹了 SVG 的基本概念、語言規范、動態特性等內容。雖然在現有的 IE 系瀏覽器上,它不能被支持,但在其它的非 IE 系的瀏覽器上能夠在一定程度上被支持,如在 Firefox 上絕大部分靜態特性能被支持。VML 是 IE 上的支持最好的矢量繪圖語言,所以在實際應用中,SVG 可以與 VML 互為補充,同樣的矢量圖形內容在 IE 中用 VML 來進行渲染,在其它的瀏覽器中用 SVG 來進行渲染。后面提到的矢量繪圖框架 Raphael 就是基于這樣的原理實現的。
?
?
HTML5 Canvas
前面介紹了兩個矢量繪圖語言 VML 和 SVG,它們兩者都是基于 XML 描述,能良好的支持矢量圖形在 Web 頁面上的繪制,并且提供一定的動態性,所以從語言和功能的設計角度來講,兩者都是很優秀的。然而,VML 和 SVG 所面臨的最大的問題是瀏覽器的支持,VML 是微軟主推的矢量繪圖語言,IE 對其支持的很完備,但其它的瀏覽器并不支持它;SVG 雖然是 W3C 的標準,但還處在發展的過程中,且缺少 IE 這一用戶量最大的瀏覽器的支持,嚴重的制約了它的發展。所以,越來越多的 Web 開發者將目光投向了 HTML5,希望能從這一未來的 HTML 標準中找到更為統一的方法。所幸的是,HTML5 中的 canvas 為這一問題提供了答案。HTML5 是一個新的 HTML 標準,它里面包含了很多現已被廣泛支持的 HTML4 中沒有的新特性,包括新的塊級元素,audio、canvas 等新的標簽、2D 繪圖、離線數據庫存儲等新的 API。而新標簽 canvas 和 2D 繪圖 API 組成了 HTML5 的繪圖功能。HTML5 中的繪圖與 VML 及 SVG 最大的不同在于前者的繪圖基本上都是通過 API 調用來完成的,而后者是通過 XML 描述來實現的。所以從直觀性和可讀性來講,VML 和 SVG 的 XML 元素能與生成的圖形一一對應,HTML5 通過 API 來繪制圖形,從開發的角度講不是很直觀,但是一些公司已經在開發一些工具來為 HTML5 繪圖提供支持,比如 Adobe 不但宣稱在 CS5 中支持 HTML5,而且在嘗試提供開發工具來支持基于 HTML5 繪圖的動畫,甚至提供工具將 Flash 動畫直接轉成 HTML5 的 canvas 格式。所以,雖然 HTML5 中的通過 API 生成矢量圖的方式不直觀,但是如果有良好的開發工具的支持,加之其本是就是一個將將被廣泛接受的通用標準,HTML5 將會成為未來 Web 上圖形開發的趨勢。
Canvas 是 HTML5 中的新的元素,用于在 Web 頁面上繪制各種矢量圖形。雖然 HTML5 還沒有被各種瀏覽器全面支持,但絕大多數現代瀏覽器都支持 canvas 元素,而 IE8 及其以下版本基本不支持 HTML5(IE8 支持少部分內容,但不支持 canvas)。令人欣慰的是,微軟最近已經證實將在 IE9 中支持 canvas 繪圖等 HTML5 關鍵標簽技術。作為 HTML 文檔中的一個 DOM 節點,canvas 支持 height 和 width 兩個屬性用于定義尺寸。定義好 canvas 節點后,可以通過它的 getContext 函數來獲得渲染上下文。一般支持 canvas 的瀏覽器都會支持 2D 繪圖的上下文,而不少的瀏覽器已經可以支持 3D 上下文,圖 5 所示的截圖就是利用 3D 上下文在 canvas 上實現仿 Counter Strike 射擊游戲。
圖 5. canvas 的 3D 上下文實現的仿 Counter Strike 射擊游戲
?
本文主要介紹 canvas 的 2D 繪圖,3D 繪圖與之是類似的。在 canvas 中,通過渲染上下文的 API 就可以繪制各種矢量圖形,包括矩形、路徑、各種線條、弧線、二次方曲線等。比較有趣的是,canvas 只支持一種基本形狀——矩形,其它的形狀都是由一個或多個路徑組合而成。清單 6 繪制了一個矩形和一個三角形。在 Firefox3.5 上的運行結果如圖 6 所示。
清單 6. 利用 HTML5 Canvas 繪制矩形和三角形
圖 6. HTML5 的 canvas 繪制的矩形和三角形
?
與 SVG 類似,HTML5 canvas 也支持引入圖像,這會提供一個非常有趣的功能就是可以利用矢量繪圖和圖像引用來進行圖像合成。清單 7 所示的就是用一個坐標圖作為背景,在上面完成曲線繪制,圖 7 是在 Firefox3 上運行的結果。
清單 7. 引入圖像的 HTML5 canvas 繪圖
圖 8. HTM5 canvas 繪制的坐標曲線
?
HTML5 的 canvas 提供通過繪圖上下文的屬性來設定圖形的顏色和式樣,如通過 fillStyle 設定圖形的填充顏色,通過 strokeStyle 設定圖形輪廓的顏色,通過 globalAlpha 來設置全局透明度,通過 lineWidth 來設置線條寬度等。如在清單 7 的代碼中加入顏色設定,就可以畫出有顏色的曲線,如清單 8 所示。
清單 8. 為坐標曲線加入顏色設定
除了上面介紹的繪制圖形、引入圖像和顏色式樣設定,HTML5 的 canvas 上的矢量繪圖還包括變形、組合等高級特性,這里就不再詳述。
如前所述,SVG 和 VML 都是通過 XML 來描述圖形對象的,每一個圖形對象都會對應一定的 DOM 樹節點,所以可以將事件處理直接綁定在圖形節點上。而 HTML canvas 是畫布的機制,除了正方形外,其余的圖形要通過畫線來完成,這就不能采取類似 SVG 和 VML 中 DOM 節點的那種直接的綁定方式。在 HTML5 的 canvas 上如果想為某個圖形綁定一個鼠標點擊事件,需要在鼠標事件的回調函數中計算鼠標點擊的位置和圖形的范圍,如果鼠標事件落在了目標圖形內,則調用圖形的鼠標點擊事件處理函數。所以,相比 SVG、XML,HTML5 canvas 在事件處理上并沒有提供高級封裝。當然,隨著 HTML5 canvas 的普及和發展,會有基于 HTML5 矢量繪圖的工具庫出現,幫助實現一定的封裝,提供一些高級的事件綁定功能。
HTML5 的 canvas 是可以實現動畫功能的,所以當前流行著一種說法是 HTML5 canvas 終將取代 Adobe 的 Flash 技術而成為未來動畫技術的標準。這兩者未來誰將成為主導不是本文的關注點,但有一點要注意的是 HTML5 并不像 Flash 那樣專門為動畫而設計。在對動畫功能的支持上,Flash 針對動畫的一些功能設計比當前的 HTML5 先進;在動畫的運行環境上,Flash 是在 Flash 播放器上運行,HTML5 canvas 是在瀏覽器上運行,前者理應更穩定更高效;在動畫的實現機制上,兩者是相同的,都是定時的刷新重繪。所以要利用 HTML5 canvas 實現動畫效果,一方面要利用其做到刷新和重繪,同時還要使用 JavaScript 中的定時器。清單 9 給出了利用 HTML5 的 canvas 實現的動畫。在其中我們設置了一個定時器,定期的清空原來畫布上的內容,然后重新繪制。
清單 9. 利用 HTML5 canvas 和 Javascipt 定時器實現的動畫
在本小節中我們介紹了 HTML5 canvas 矢量繪圖的一些基本概念、常用 API、動態交互以及動畫效果的實現,相比較 SVG 和 VML,HTML canvas 針對的是更為底層的繪圖功能,但是利用這些底層的 API,通過良好的結構功能設計和封裝,完全可以實現功能強的易用性更好的組件庫,這在我們的后續文章中介紹。
?
?
開源矢量繪圖框架 Raphael
Raphael 是一個很小的輕量級矢量繪圖類庫。正如其名,它能讓你像文藝復興時期意大利畫家拉斐爾一樣在 Web 頁面上繪制出復雜絢麗的矢量圖形。Raphael 使用 W3C 推薦的 SVG 和 VML 為矢量繪圖的基礎,對于目前主流的 Firefox、Webkit、Opearo 瀏覽器上 Raphael 使用 SVG 繪制圖形,對于 IE6/7/8 瀏覽器 Raphael 使用 VML 來繪制圖形。Raphael 在瀏覽器中創建的所有圖形對象都是一個 HTML DOM 對象,這樣你就可以使用 JavaScript 為其添加事件和響應,通過 JavaScript 方法來動態的改變圖像對象,從而實現任何你想要的動畫效果。Raphael 為 Web 開發人員在瀏覽器中創建矢量圖形提供了一個橋梁,它簡化了 Web 應用中矢量兩會圖開發,從此你不必再為跨瀏覽器、使用和維護各種不同的矢量繪圖技術而頭疼。目前 Raphael 支持 Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+ 等瀏覽器。
使用 Raphael 創建矢量圖形非常簡單,下面是一些使用 Raphael 的一些代碼和圖形示例。
清單 10. 使用 Raphael 創建矢量圖形代碼示例
//?在坐標點?10,?50?位置創建一個?320?×?200?大小的畫布??varpaper?=?Raphael(10,?50,?320,?200);??//?在?x?=?50,?y?=?40?位置畫一個半徑為?10?的圓形?varcircle?=?paper.circle(50,?40,?10);??//?使用紅色?(#f00)?來填充這個圓形?circle.attr("fill",?"#f00");???//?設置畫筆為白色?circle.attr("stroke",?"#fff");
圖 9. 使用 Raphael 繪制的一些矢量圖形
?
?
?
?
對于矢量繪圖的幾點建議
雖然 Web 下的矢量繪圖功能十分強大, 但由于很多實際原因這部分技術并沒有被廣泛應用。在此根我們對矢量繪圖的使用經驗給出一些使用矢量繪圖的建議:
對于一些以實驗為目的、非正式商用或者一些特殊需求的應用,大可不必考慮瀏覽器過多的兼容性等問題,使得問題變得過于復雜。可直接使用 HTML5 的 canvas。
對于嚴格要求眾多瀏覽器兼容性的應用,可以通過動態判斷瀏覽器的類型在 IE 中使用 VML,在其他瀏覽器中使用 SVG。但更推薦直接使用 Raphael 開源類庫。
盡量控制矢量繪圖的使用范圍,使得如果矢量繪圖技術在本地瀏覽器不可用時,不影響基本功能的使用。例如:利用矢量繪圖繪制報表圖形,廣告,等等。
?
小結
隨著當今社會對各種產品和服務的用戶體驗的要求越來越來高,矢量繪圖在 Web 頁面開發中的重要性與日俱增。本文對當前主流的三種 Web 矢量繪圖技術進行了詳細的介紹。并以開源項目 Raphael 為例介紹了混合矢量繪圖技術。在此基礎上對 Web 應用中如何使用矢量繪圖技術給出了一些建議。雖然,如本文所述,Web 上的矢量繪圖技術暫時還沒有哪一種能成為主導,但是隨著技術的發展和需求的增強,終將會有一、兩種已存在的或新的矢量繪圖技術脫穎而出并被廣泛接受和使用,把我們的網絡生活裝扮的更加“豐富多彩”。
轉載于:https://my.oschina.net/parker/blog/202835
總結
以上是生活随笔為你收集整理的Web开发中的矢量绘图(vml,svg)处理和应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TinyUI组件开发示例
- 下一篇: Linux脚本利器sed