国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Web 開發(fā)中的矢量繪圖處理和應(yīng)用
秦 劍, 邵 煜, 和 陳 序明
2011 年 9 月 01 日發(fā)布

前言

1991 年物理學(xué)家 Tim Berners-Lee 首次在因特網(wǎng)上發(fā)布了 HTML 的第一版描述規(guī)范文檔。經(jīng)過了 20 多年的發(fā)展,HTML 語言成為如今編程最為廣泛的語言和互聯(lián)網(wǎng)上采用最廣的文檔格式。雖然 HTML 發(fā)展十分迅速并具有諸多優(yōu)點(diǎn),但其始終不能提供一個(gè)良好的矢量繪圖解決方案。很多應(yīng)用為獲得絢麗的動畫和繪圖效果,不得已在頁面中嵌入大量的 Flash。這不僅降低了頁面元素的交互性,大量的 Flash 同時(shí)嚴(yán)重影像了頁面性能,更加頭疼的是 Flash 內(nèi)容不能被搜索引擎搜索。雖然有良好的跨瀏覽器特性,但是用戶不得不安裝一個(gè)瀏覽器插件。

本文首先針對不同瀏覽器詳細(xì)闡述不同的矢量繪圖解決方案,其中包括 HTML5 Canvas、SVG 以及 VML 等技術(shù);之后針對每種不同的技術(shù)介紹其實(shí)現(xiàn)和使用方法;最后本文將介紹如何創(chuàng)建一個(gè)跨瀏覽器的矢量繪圖應(yīng)用,并對當(dāng)前的一些快瀏覽器矢量繪圖框架進(jìn)行簡單介紹。

VML

VML ( Vector Markup Language ) 矢量可標(biāo)記語言是一種基于 XML 語法的矢量繪圖語言。1998 年由 Autodesk ,Hewlett-Packard ,MacromediaMicrosoft 幾家公司共同向 W3C 提交,并希望能夠成為矢量繪圖的國際化標(biāo)準(zhǔn)。雖然 VML 最終沒有成為 W3C 推薦的矢量繪圖標(biāo)準(zhǔn),但其還是被大量應(yīng)用于 MS Office、Visio 等軟件和 IE 瀏覽器中。由于 Office 和 IE 的成功和其廣闊的市場占有率,VML 已經(jīng)成為在 IE 中首選的矢量繪圖語言。

由于 VML 基于 XML 標(biāo)準(zhǔn)的矢量繪圖語言,VML 先天性的具有表示方法簡單、易于擴(kuò)展等優(yōu)勢。簡單的一行標(biāo)記代碼就可以使開發(fā)人員快速繪制輸出線段、圓形、矩形、圓矩形、曲線、多邊形、弧型等矢量圖形。并且可以通過修飾這些原色的邊框、陰影、填充、背景、漸變、箭頭等等來增強(qiáng)和提升其外觀效果。同時(shí)由于 VML 與 HTML 兼容,可以將 VML 與 HTML 混合在一起使用。VML 所繪制的每一個(gè)圖形,都跟 HTML 元素一樣是一個(gè)圖形對象,同樣支持 DHTML 對象編程模型、DHTML 事件編程模型。因此開發(fā)人員可以利用 JavaScript 等腳本輕松的讀取、更改 VML 圖形對象的各種屬性,響應(yīng)用戶觸發(fā)的鼠標(biāo)、鍵盤等事件,實(shí)現(xiàn)與用戶交互。如果有機(jī)的配合定時(shí)器和一些其他模型,則能實(shí)現(xiàn)類似 Flash 般復(fù)雜的動畫,輸出高質(zhì)量質(zhì)量動畫效果。

VML 的使用非常簡單,它采用 HTML 的標(biāo)簽方式來定義和繪制圖像。例如下面的代碼所示:

清單 1.VML 代碼示例
1
2
3
4
5
6
<html xmlns:v="urn:schemas-microsoft-com:vml">
<style>v\:*{behavior:url(#default#VML);position:absolute}</style>
<body>
<v:oval style="left:0;top:0;width:100;height:50" fillcolor="blue"/>
</body>
</html>

如清單 1 所示,上面代碼是一段簡單的 VML 示例代碼,繪制出一個(gè)藍(lán)色的橢圓形。其中 xmlns 標(biāo)記的全稱是 XML NameSpace,用來指定該文檔的命名空間。 Behavior 是 IE5.0 版本以后推出的一個(gè)非常強(qiáng)大功能。通常情況下 Behavior 與樣式表結(jié)合一起使用,給任何 HTML 對象增加新的行為,例如新的屬性、方法、事件等等。在上面的示例代碼中,Behavior 的用處是把命名空間“v”和系統(tǒng)預(yù)定義的行為 VML 連接起來,提供系統(tǒng)默認(rèn)的 VML 功能。v:oval 標(biāo)簽則定義一個(gè)橢圓形的 VML 圖形,fillcolor 屬性指定該圖形用藍(lán)色來填充。

圖 1. 清單 1 示例代碼效果圖

VML 默認(rèn)定義了許多圖形元素,包括:Shape 基本抽象形狀,它在 VML 中代表任何形狀;Line 直線或者線段;Polyline 代表特殊的線段,它將 Points 屬性所指定的一系列的點(diǎn)連接起來;Rect 代表矩形對象,它在流程圖的繪制中非常常用;Roundrect 顧名思義為圓角矩形,它的功能和矩形對象基本上同;Oval 是 VML 中的圓形對象,你可以定義它的寬度和高度來得到不同的橢圓形狀,還可以通過指定 arc 弧屬性來繪制一個(gè)圓上一段弧度,利用 Oval 對象我們可以繪制出各種我們想要的曲線;Group 是 VML 中的一個(gè)容器標(biāo)簽,它的使用很簡單,但功能很強(qiáng)大。它能讓一系列的 VML 對象使用共同的坐標(biāo)系和縮放尺度,這樣改變 CoordSize 值可以使得這一組圖形的坐標(biāo)和縮放尺度一起改變。Group 經(jīng)常被用來實(shí)現(xiàn)一組適量圖形的動態(tài)放大和縮小。

VML 看似簡單的標(biāo)簽和屬性卻定義了很多功能強(qiáng)大的組件。將這些圖形標(biāo)簽組合在一起使用可以繪制出很多漂亮、復(fù)雜甚至是令人難以想象的畫面,例如下圖就是一個(gè)利用 VML 繪制出的《蒙娜麗莎》畫像。如果在于 JavaScript 等腳本混合使用,可以繪制出和 Flash 一樣絢麗的動畫和游戲效果。

圖 2. VML 在 IE 瀏覽器中繪制出的《蒙娜麗莎》畫像

SVG

SVG 是可擴(kuò)展矢量圖(Scalable Vector Graphics)的簡稱,它是 W3C 組織為適應(yīng)因特網(wǎng)的飛速發(fā)展而制定的一套基于 XML 語言的二維矢量圖形的語言描述規(guī)范。W3C 中的 SVG 開發(fā)工作組的的成員包括了 IBM、Adobe、Apple、Microsoft、AutoDesk 等一批知名廠商,使其成為了通用的標(biāo)準(zhǔn)。而且隨著移動通訊的迅猛發(fā)展,W3C 又推出了 SVG 的移動版本,并被多個(gè)移動設(shè)備廠商的多個(gè)型號的手機(jī)所支持,并成為 3G 時(shí)代的一個(gè)重要的技術(shù)標(biāo)準(zhǔn)。在 PC 平臺上,由于 SVG 常用于豐富 Web 頁面內(nèi)容,一部分瀏覽器已經(jīng)提供了對 SVG 格式的一些支持,如 Firefox、Safari 等,而 IE 系列瀏覽器中的 IE6,、IE7 和 IE8 都沒有對 SVG 提供支持。但微軟顯然已經(jīng)意識到 SVG 標(biāo)準(zhǔn)的已經(jīng)變得越來越普及,所以不但加入了 W3C 下面的 SVG 工作小組,更是在已經(jīng)發(fā)布的 IE9 的 Beta 版中提供了對 SVG 基本特性的支持。值得注意的是,雖然很多瀏覽器甚至微軟的 IE9 都已經(jīng)對 SVG 提供一定的支持,但是其中不少只是支持 SVG 標(biāo)準(zhǔn)的部分功能,如果想讓這些瀏覽器全面支持 SVG 標(biāo)準(zhǔn),需要安裝一些 SVG 的瀏覽插件,比如 Adobe SVG Viewer。借助這些 SVG 插件,瀏覽器上可支持絕大部分現(xiàn)有 SVG 規(guī)范中的內(nèi)容,這里說“絕大部分”是因?yàn)?SVG 至今仍然是一個(gè)發(fā)展的標(biāo)準(zhǔn),現(xiàn)在和將來的都會有一些新的變化,這些 SVG 瀏覽插件只會支持在某個(gè)穩(wěn)定版本下的確定的功能。當(dāng)前 SVG 的穩(wěn)定版本是 W3C 于 2003 年 1 月份發(fā)布的 SVG1.1,后續(xù)版本 SVG1.2 正在研究制定的過程中。

SVG 遵循 XML 格式的描述語言來描述矢量圖形的內(nèi)容,支持三種矢量顯示對象,包括矢量圖形對象(矩形、圓,曲線等)、嵌入式外部對象(PNG、JPEG、SVG 等)和文字對象。SVG 最終的文件格式是文本,對開發(fā)人員來說具有良好的可讀性和可擴(kuò)展性。平均來講,SVG 文件的大小要小于 JPEG 等其他的網(wǎng)絡(luò)圖形格式,而且 SVG 支持利用 gzip 壓縮算法進(jìn)行壓縮從而獲得很大的壓縮比,壓縮后生成的文件格式為 SVGZ。因?yàn)?SVG 中的矢量顯示對象是被描述出來的,所以支持無損的放大縮小,而對于那些柵格圖形格式,如 BMP,JPEG 等,放大或是縮小需要利用數(shù)值算法進(jìn)行插值而造成失真。SVG 圖形格式支持文字對象,可以很方便的建立文字索引,進(jìn)而實(shí)現(xiàn)基于內(nèi)容的圖像搜索。SVG 格式支持多種濾鏡和特殊效果,如給文字內(nèi)容加上陰影。此外,最重要的一點(diǎn)是 SVG 具有良好的動態(tài)性,一方面自身的有基于 SMIL(Synchronized Multimedia Integration Language,同步多媒體集成語言)標(biāo)準(zhǔn)的動態(tài)內(nèi)容;另一方面可以利用 JavaScript 腳本來控制對象,來提供良好的互動。SVG 的這些特性使其得到了廣泛的支持和應(yīng)用。

SVG 通過多種標(biāo)簽元素來構(gòu)成整個(gè)的矢量圖形,包括根元素 svg,圖形對象:rect(矩形)、circle(圓)、ellipse(橢圓)、line(線)、polygon(多邊形)、polyline(多直線圖形)、path(路徑生成圖形)等。濾鏡效果:feBlend、feColorMatrix、feComponentTransfer、feComposite、feConvolveMatrix 等,漸變效果:線性漸變和徑向漸變。SVG 文檔一般是以獨(dú)立的文件存在的,并且以 .svg 作為擴(kuò)展名,如果是 GZIP 壓縮過的文件則以 .svgz 作為擴(kuò)展名。下面的清單 2 是一個(gè) SVG 靜態(tài)圖形文件的例子,其中先是定義了一個(gè)高斯濾鏡的效果和一個(gè)線性梯度的效果,隨后定義了一個(gè)正方形和一個(gè)橢圓,將已定義線性梯度應(yīng)用于前者,高斯濾鏡應(yīng)用于后者。將清單 2 中的內(nèi)容保存到一個(gè)文本文件并以 svg 作為擴(kuò)展名,用 1.5 以上版本的 Firefox 瀏覽器打開,就會看到圖 3 中所示的內(nèi)容。

清單 2. SVG 靜態(tài)圖形的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<svg version="1.1" width="500" height="500"  xmlns="http://www.w3.org/2000/svg" >
  <defs>
     <filter id="Gaussian_Blur">
        <feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
     </filter>
     <linearGradient id="Gradient_Linear" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
     </linearGradient>
  </defs>
  <rect x="12" y="12" width="100" height="80" style="fill:url(#Gradient_Linear)"/>
  <ellipse cx="240" cy="100" rx="100" ry="50"
  style="fill:purple;stroke:#000000;stroke-width:2;filter:url(#Gaussian_Blur)"/>
</svg>
圖 3. SVG 靜態(tài)圖形在 Firefox 瀏覽器中的展現(xiàn)

上面的例子是用 Firefox 直接打開 SVG 文檔文件來瀏覽,但是在一般的 Web 應(yīng)用中,更多的情況是將 SVG 文檔嵌入到 HTML 頁面中,在瀏覽器渲染頁面的時(shí)候直接將 SVG 的圖像渲染到展現(xiàn)頁面上。將 SVG 圖形嵌入 HTML 頁有四種方式:通過 object 標(biāo)簽,通過 embed 標(biāo)簽,通過 iframe 標(biāo)簽和直接將 SVG 的內(nèi)容嵌入到頁面中。然而,現(xiàn)在支持 SVG 的主流的瀏覽器包括 Firefox、Safari 等不支持將 SVG 內(nèi)容直接嵌入的方式,對另外三種方式基本能夠支持。清單 3 給出了利用 object 標(biāo)簽、embed 標(biāo)簽和 iframe 標(biāo)簽將上面的 SVG 文檔嵌入 HTML 頁面的例子。圖 4 給出了這個(gè) HTML 文檔在 Firefox 上的展現(xiàn)結(jié)果。

清單 3. 嵌入 SVG 文檔的 HTML 頁面
1
2
3
4
5
6
7
8
9
10
11
12
13
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
     <title>SVG as embedded object and nested namespace</title>
  </head>
  <body>
     <h2>Object</h2>
     <object type="image/svg+xml" data="svg1.svg" ></object>
     <h2>IFrame</h2>
     <iframe  src ="svg1.svg"  width ="500"  height ="200" frameborder="no"></iframe>
     <h2>Embed</h2>
     <embed src="svg1.svg" />
  </body>
</html>
圖 4. Firefox 打開的嵌入 SVG 文檔的 HTML 頁面

SVG 支持的動態(tài)特性既包括 SVG 圖像自身的動畫也包括 SVG 圖像的各種交互功能。SVG 的動畫是 SVG 規(guī)范中的特性,使用不同的標(biāo)簽元素來聲明,它們中有一部分是在 SMIL 定義的,如 animate、set、animateMotion 和 animateColor,剩下的則是 SVG 標(biāo)準(zhǔn)擴(kuò)展的,如 animateTransform。另外,SVG 還為 animateMotion 標(biāo)簽元素添加了三個(gè)屬性:path、keyPoints、rotate,以及一個(gè)子標(biāo)簽元素 mpath。在下面的例子中,我們將用 animate 和 set 來實(shí)現(xiàn)一些效果。animate 允許一個(gè)圖形元素的某個(gè)屬性的值在一段時(shí)間內(nèi)等量的變化,而 set 則是在一段時(shí)間內(nèi)將值賦給某個(gè)屬性,具體如清單 4 中的代碼所示。由于 Firefox3. 版本不支持 SVG 的動畫,所以這段文檔中動畫需要用其他支持 SVG 動畫的瀏覽器如 Safari 或是安裝 SVG Viewer 才可瀏覽。

清單 4. 加入動畫效果的 SVG 文檔
1
2
3
4
5
6
7
8
9
10
11
12
13
<svg version="1.1" width="500" height="200"  xmlns="http://www.w3.org/2000/svg" >
  <defs>
     <linearGradient id="Gradient_Linear" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
     </linearGradient>
  </defs>
  <rect x="12" y="12" width="100" height="80" style="fill:url(#Gradient_Linear)">
     <animate attributeName="width" to="300" dur="5s" fill="freeze"/>
     <animate attributeName="width" to="100" begin="5s" dur="5s" fill="freeze"/>
     <set attributeName="fill" to="yellow" begin="3s" dur="4s"/>
  </rect>
</svg>

SVG 圖像的交互包括 SVG 中的鏈接、事件響應(yīng)以及腳本支持。SVG 中的每一個(gè)圖形對象都可以包裝在不同的鏈接標(biāo)簽里面。與 HTML 中的鏈接的標(biāo)簽相同,SVG 也使用 <a> 來表示鏈接,將其與一個(gè) xlink:href 屬性結(jié)合就可以建立一個(gè)鏈接。<a> 和 </a> 標(biāo)簽之間的所有內(nèi)容作為鏈接點(diǎn)。SVG 標(biāo)準(zhǔn)支持鼠標(biāo)和鍵盤事件,可以在 XML 描述文檔中直接定義對這些事件的監(jiān)聽和響應(yīng),這些響應(yīng)一般是某個(gè)動畫設(shè)定,通過上文提到的 set、animate 等來實(shí)現(xiàn)。雖然通過 SVG 的 XML 元素已經(jīng)可以實(shí)現(xiàn)一定的動畫效果和事件響應(yīng),但如果想要實(shí)現(xiàn)更復(fù)雜的邏輯就需要腳本的支持。SVG 支持通過 JavaScript 腳本訪問 SVG 文檔構(gòu)成的 DOM 節(jié)點(diǎn)樹,查詢、修改 DOM 節(jié)點(diǎn)的屬性,調(diào)用其公開的方法,監(jiān)聽其發(fā)布的事件。JavaScript 腳本可以通過 script 元素直接嵌入到 SVG 文檔中或是通過 script 的 xlink:href 來從外部腳本文件引入。清單 5 中給出的例子是在清單 4 的基礎(chǔ)上加入了些 JavaScript 腳本,實(shí)現(xiàn)了對原正方形的矢量圖形的鼠標(biāo)單擊事件的響應(yīng)。這個(gè)事件處理的函數(shù)中進(jìn)行了一些節(jié)點(diǎn)添加和刪除的操作:將包含“IBM”文本的 Text 節(jié)點(diǎn)刪掉,創(chuàng)建了一個(gè)包含“BTT”文本的 Text 節(jié)點(diǎn)并添加到 SVG 的 DOM 樹中。

清單 5. 加入 JavaScript 腳本的 SVG 文檔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<svg version="1.1" width="500" height="200"  xmlns="http://www.w3.org/2000/svg" >
  <defs>
     <linearGradient id="Gradient_Linear" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
     </linearGradient>
  </defs>
  <rect id="rect1" onclick="showBTT()" x="12" y="12" width="100" height="80"
  style="fill:url(#Gradient_Linear)">
     <animate id="a1" attributeName="width"
     begin="click" to="300" dur="5s" fill="freeze"/>
     <animate attributeName="width" to="100" begin="a1.end" dur="5s" fill="freeze"/>
     <set attributeName="fill"  to="yellow" begin="a1.begin + 3s" dur="4s"/>
  </rect>
  <g id="g1" transform="translate(25,120)" fill="red" font-size="25">
     <text>IBM</text>
  </g>
  <script language="JavaScript">
     <![CDATA[
        function showBTT() {
           var g1=document.getElementById("g1");
           var txts=g1.getElementsByTagName("text");
           for(var i=txts.length-1;i>=0;i--){
              g1.removeChild(txts.item(i));
           }
           var text = document.createElementNS("http://www.w3.org/2000/svg","text");
           text.appendChild(document.createTextNode("BTT"));
              g1.appendChild(text);
        }
     ]]>
  </script>
</svg>

在本小節(jié)中,我們介紹了 SVG 的基本概念、語言規(guī)范、動態(tài)特性等內(nèi)容。雖然在現(xiàn)有的 IE 系瀏覽器上,它不能被支持,但在其它的非 IE 系的瀏覽器上能夠在一定程度上被支持,如在 Firefox 上絕大部分靜態(tài)特性能被支持。VML 是 IE 上的支持最好的矢量繪圖語言,所以在實(shí)際應(yīng)用中,SVG 可以與 VML 互為補(bǔ)充,同樣的矢量圖形內(nèi)容在 IE 中用 VML 來進(jìn)行渲染,在其它的瀏覽器中用 SVG 來進(jìn)行渲染。后面提到的矢量繪圖框架 Raphael 就是基于這樣的原理實(shí)現(xiàn)的。

HTML5 Canvas

前面介紹了兩個(gè)矢量繪圖語言 VML 和 SVG,它們兩者都是基于 XML 描述,能良好的支持矢量圖形在 Web 頁面上的繪制,并且提供一定的動態(tài)性,所以從語言和功能的設(shè)計(jì)角度來講,兩者都是很優(yōu)秀的。然而,VML 和 SVG 所面臨的最大的問題是瀏覽器的支持,VML 是微軟主推的矢量繪圖語言,IE 對其支持的很完備,但其它的瀏覽器并不支持它;SVG 雖然是 W3C 的標(biāo)準(zhǔn),但還處在發(fā)展的過程中,且缺少 IE 這一用戶量最大的瀏覽器的支持,嚴(yán)重的制約了它的發(fā)展。所以,越來越多的 Web 開發(fā)者將目光投向了 HTML5,希望能從這一未來的 HTML 標(biāo)準(zhǔn)中找到更為統(tǒng)一的方法。所幸的是,HTML5 中的 canvas 為這一問題提供了答案。HTML5 是一個(gè)新的 HTML 標(biāo)準(zhǔn),它里面包含了很多現(xiàn)已被廣泛支持的 HTML4 中沒有的新特性,包括新的塊級元素,audio、canvas 等新的標(biāo)簽、2D 繪圖、離線數(shù)據(jù)庫存儲等新的 API。而新標(biāo)簽 canvas 和 2D 繪圖 API 組成了 HTML5 的繪圖功能。HTML5 中的繪圖與 VML 及 SVG 最大的不同在于前者的繪圖基本上都是通過 API 調(diào)用來完成的,而后者是通過 XML 描述來實(shí)現(xiàn)的。所以從直觀性和可讀性來講,VML 和 SVG 的 XML 元素能與生成的圖形一一對應(yīng),HTML5 通過 API 來繪制圖形,從開發(fā)的角度講不是很直觀,但是一些公司已經(jīng)在開發(fā)一些工具來為 HTML5 繪圖提供支持,比如 Adobe 不但宣稱在 CS5 中支持 HTML5,而且在嘗試提供開發(fā)工具來支持基于 HTML5 繪圖的動畫,甚至提供工具將 Flash 動畫直接轉(zhuǎn)成 HTML5 的 canvas 格式。所以,雖然 HTML5 中的通過 API 生成矢量圖的方式不直觀,但是如果有良好的開發(fā)工具的支持,加之其本是就是一個(gè)將將被廣泛接受的通用標(biāo)準(zhǔn),HTML5 將會成為未來 Web 上圖形開發(fā)的趨勢。

Canvas 是 HTML5 中的新的元素,用于在 Web 頁面上繪制各種矢量圖形。雖然 HTML5 還沒有被各種瀏覽器全面支持,但絕大多數(shù)現(xiàn)代瀏覽器都支持 canvas 元素,而 IE8 及其以下版本基本不支持 HTML5(IE8 支持少部分內(nèi)容,但不支持 canvas)。令人欣慰的是,微軟最近已經(jīng)證實(shí)將在 IE9 中支持 canvas 繪圖等 HTML5 關(guān)鍵標(biāo)簽技術(shù)。作為 HTML 文檔中的一個(gè) DOM 節(jié)點(diǎn),canvas 支持 height 和 width 兩個(gè)屬性用于定義尺寸。定義好 canvas 節(jié)點(diǎn)后,可以通過它的 getContext 函數(shù)來獲得渲染上下文。一般支持 canvas 的瀏覽器都會支持 2D 繪圖的上下文,而不少的瀏覽器已經(jīng)可以支持 3D 上下文,圖 5 所示的截圖就是利用 3D 上下文在 canvas 上實(shí)現(xiàn)仿 Counter Strike 射擊游戲。

圖 5. canvas 的 3D 上下文實(shí)現(xiàn)的仿 Counter Strike 射擊游戲

本文主要介紹 canvas 的 2D 繪圖,3D 繪圖與之是類似的。在 canvas 中,通過渲染上下文的 API 就可以繪制各種矢量圖形,包括矩形、路徑、各種線條、弧線、二次方曲線等。比較有趣的是,canvas 只支持一種基本形狀——矩形,其它的形狀都是由一個(gè)或多個(gè)路徑組合而成。清單 6 繪制了一個(gè)矩形和一個(gè)三角形。在 Firefox3.5 上的運(yùn)行結(jié)果如圖 6 所示。

清單 6. 利用 HTML5 Canvas 繪制矩形和三角形
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<html>
  <head>
     <script>
        window.onload = function() {
           var canvas = document.getElementById('canvas1');
           var ctx = canvas.getContext('2d');
           ctx.fillRect(25,25,100,100);
           ctx.clearRect(45,45,60,60);
           ctx.strokeRect(50,50,50,50);
           ctx.beginPath();
  ctx.moveTo(125,125);
  ctx.lineTo(205,125);
  ctx.lineTo(125,205);
           ctx.fill();
        }
     </script>
  </head>
  <body>
     <canvas id="canvas1" height="600" width="600">
     </canvas>
  </body>
</html>
圖 6. HTML5 的 canvas 繪制的矩形和三角形

與 SVG 類似,HTML5 canvas 也支持引入圖像,這會提供一個(gè)非常有趣的功能就是可以利用矢量繪圖和圖像引用來進(jìn)行圖像合成。清單 7 所示的就是用一個(gè)坐標(biāo)圖作為背景,在上面完成曲線繪制,圖 7 是在 Firefox3 上運(yùn)行的結(jié)果。

清單 7. 引入圖像的 HTML5 canvas 繪圖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
  <head>
     <script>
        window.onload = function() {
           var canvas = document.getElementById('canvas1');
           var ctx = canvas.getContext('2d');
           var img = new Image(); 
           img.onload = function(){ 
              ctx.drawImage(img,0,0); 
              ctx.beginPath(); 
              ctx.moveTo(30,96); 
              ctx.lineTo(70,66); 
              ctx.lineTo(103,76); 
              ctx.lineTo(170,15); 
              ctx.stroke(); 
           
           img.src = 'coordinate.png'
        }
     </script>
  </head>
  <body>
     <canvas id="canvas1" height="600" width="600"></canvas>
  </body>
</html>
圖 8. HTM5 canvas 繪制的坐標(biāo)曲線

HTML5 的 canvas 提供通過繪圖上下文的屬性來設(shè)定圖形的顏色和式樣,如通過 fillStyle 設(shè)定圖形的填充顏色,通過 strokeStyle 設(shè)定圖形輪廓的顏色,通過 globalAlpha 來設(shè)置全局透明度,通過 lineWidth 來設(shè)置線條寬度等。如在清單 7 的代碼中加入顏色設(shè)定,就可以畫出有顏色的曲線,如清單 8 所示。

清單 8. 為坐標(biāo)曲線加入顏色設(shè)定
1
2
3
4
5
6
7
8
9
10
11
img.onload = function(){ 
  ctx.drawImage(img,0,0);
  // 顏色設(shè)定
  ctx.strokeStyle = 'rgb(255, 0, 0)';
  ctx.beginPath(); 
  ctx.moveTo(30,96); 
  ctx.lineTo(70,66); 
  ctx.lineTo(103,76); 
  ctx.lineTo(170,15); 
  ctx.stroke(); 
}

除了上面介紹的繪制圖形、引入圖像和顏色式樣設(shè)定,HTML5 的 canvas 上的矢量繪圖還包括變形、組合等高級特性,這里就不再詳述。

如前所述,SVG 和 VML 都是通過 XML 來描述圖形對象的,每一個(gè)圖形對象都會對應(yīng)一定的 DOM 樹節(jié)點(diǎn),所以可以將事件處理直接綁定在圖形節(jié)點(diǎn)上。而 HTML canvas 是畫布的機(jī)制,除了正方形外,其余的圖形要通過畫線來完成,這就不能采取類似 SVG 和 VML 中 DOM 節(jié)點(diǎn)的那種直接的綁定方式。在 HTML5 的 canvas 上如果想為某個(gè)圖形綁定一個(gè)鼠標(biāo)點(diǎn)擊事件,需要在鼠標(biāo)事件的回調(diào)函數(shù)中計(jì)算鼠標(biāo)點(diǎn)擊的位置和圖形的范圍,如果鼠標(biāo)事件落在了目標(biāo)圖形內(nèi),則調(diào)用圖形的鼠標(biāo)點(diǎn)擊事件處理函數(shù)。所以,相比 SVG、XML,HTML5 canvas 在事件處理上并沒有提供高級封裝。當(dāng)然,隨著 HTML5 canvas 的普及和發(fā)展,會有基于 HTML5 矢量繪圖的工具庫出現(xiàn),幫助實(shí)現(xiàn)一定的封裝,提供一些高級的事件綁定功能。

HTML5 的 canvas 是可以實(shí)現(xiàn)動畫功能的,所以當(dāng)前流行著一種說法是 HTML5 canvas 終將取代 Adobe 的 Flash 技術(shù)而成為未來動畫技術(shù)的標(biāo)準(zhǔn)。這兩者未來誰將成為主導(dǎo)不是本文的關(guān)注點(diǎn),但有一點(diǎn)要注意的是 HTML5 并不像 Flash 那樣專門為動畫而設(shè)計(jì)。在對動畫功能的支持上,F(xiàn)lash 針對動畫的一些功能設(shè)計(jì)比當(dāng)前的 HTML5 先進(jìn);在動畫的運(yùn)行環(huán)境上,F(xiàn)lash 是在 Flash 播放器上運(yùn)行,HTML5 canvas 是在瀏覽器上運(yùn)行,前者理應(yīng)更穩(wěn)定更高效;在動畫的實(shí)現(xiàn)機(jī)制上,兩者是相同的,都是定時(shí)的刷新重繪。所以要利用 HTML5 canvas 實(shí)現(xiàn)動畫效果,一方面要利用其做到刷新和重繪,同時(shí)還要使用 JavaScript 中的定時(shí)器。清單 9 給出了利用 HTML5 的 canvas 實(shí)現(xiàn)的動畫。在其中我們設(shè)置了一個(gè)定時(shí)器,定期的清空原來畫布上的內(nèi)容,然后重新繪制。

清單 9. 利用 HTML5 canvas 和 Javascipt 定時(shí)器實(shí)現(xiàn)的動畫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<html>
  <head>
     <script>
        window.onload = function() {
           var dx = -1;
           var dy = 0;
           var x = 125;
           var y = 125;
           setInterval(function(){
              var canvas = document.getElementById('canvas1');
              var ctx = canvas.getContext('2d');
              ctx.clearRect(0,0,600,600); 
              ctx.fillStyle = 'rgb(255, 0, 0)';
              ctx.strokeStyle = 'rgb(255, 0, 0)';
              ctx.fillRect(25,25,100,100);
              ctx.clearRect(45,45,60,60);
              ctx.strokeRect(50,50,50,50);
              ctx.fillStyle = 'rgb(0, 0, 255)';
              ctx.strokeStyle = 'rgb(0, 0, 255)';   
              ctx.beginPath();
              x += dx;
              y += dy;
              ctx.moveTo(x,y);
              ctx.lineTo(x + 80, y);
              ctx.lineTo(x, y + 80);
              ctx.fill();
              if(x == 25 ) {
                 dx = 1;
              }
              if(y == 25) {
                 dy = 1;
              }
              if(x == 125 && y == 125) {
                 if(dx == 1) {
                    dy = -1
                    dx = 0;
                 }
                 if(dy == 1) {
                    dx = -1;
                    dy = 0;
                 }
              }
           },50);
        }
     </script>
  </head>
  <body>
     <canvas id="canvas1" height="600" width="600">
     </canvas>
  </body>
</html>

在本小節(jié)中我們介紹了 HTML5 canvas 矢量繪圖的一些基本概念、常用 API、動態(tài)交互以及動畫效果的實(shí)現(xiàn),相比較 SVG 和 VML,HTML canvas 針對的是更為底層的繪圖功能,但是利用這些底層的 API,通過良好的結(jié)構(gòu)功能設(shè)計(jì)和封裝,完全可以實(shí)現(xiàn)功能強(qiáng)的易用性更好的組件庫,這在我們的后續(xù)文章中介紹。

開源矢量繪圖框架 Raphael

Raphael 是一個(gè)很小的輕量級矢量繪圖類庫。正如其名,它能讓你像文藝復(fù)興時(shí)期意大利畫家拉斐爾一樣在 Web 頁面上繪制出復(fù)雜絢麗的矢量圖形。Raphael 使用 W3C 推薦的 SVG 和 VML 為矢量繪圖的基礎(chǔ),對于目前主流的 Firefox、Webkit、Opearo 瀏覽器上 Raphael 使用 SVG 繪制圖形,對于 IE6/7/8 瀏覽器 Raphael 使用 VML 來繪制圖形。Raphael 在瀏覽器中創(chuàng)建的所有圖形對象都是一個(gè) HTML DOM 對象,這樣你就可以使用 JavaScript 為其添加事件和響應(yīng),通過 JavaScript 方法來動態(tài)的改變圖像對象,從而實(shí)現(xiàn)任何你想要的動畫效果。Raphael 為 Web 開發(fā)人員在瀏覽器中創(chuàng)建矢量圖形提供了一個(gè)橋梁,它簡化了 Web 應(yīng)用中矢量兩會圖開發(fā),從此你不必再為跨瀏覽器、使用和維護(hù)各種不同的矢量繪圖技術(shù)而頭疼。目前 Raphael 支持 Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+ 等瀏覽器。

使用 Raphael 創(chuàng)建矢量圖形非常簡單,下面是一些使用 Raphael 的一些代碼和圖形示例。

清單 10. 使用 Raphael 創(chuàng)建矢量圖形代碼示例

1
2
3
4
5
6
7
8
9
10
// 在坐標(biāo)點(diǎn) 10, 50 位置創(chuàng)建一個(gè) 320 × 200 大小的畫布
varpaper = Raphael(10, 50, 320, 200);
// 在 x = 50, y = 40 位置畫一個(gè)半徑為 10 的圓形
varcircle = paper.circle(50, 40, 10);
// 使用紅色 (#f00) 來填充這個(gè)圓形
circle.attr("fill", "#f00");
// 設(shè)置畫筆為白色
circle.attr("stroke", "#fff");
圖 9. 使用 Raphael 繪制的一些矢量圖形

對于矢量繪圖的幾點(diǎn)建議

雖然 Web 下的矢量繪圖功能十分強(qiáng)大, 但由于很多實(shí)際原因這部分技術(shù)并沒有被廣泛應(yīng)用。在此根我們對矢量繪圖的使用經(jīng)驗(yàn)給出一些使用矢量繪圖的建議:

  • 對于一些以實(shí)驗(yàn)為目的、非正式商用或者一些特殊需求的應(yīng)用,大可不必考慮瀏覽器過多的兼容性等問題,使得問題變得過于復(fù)雜。可直接使用 HTML5 的 canvas。

  • 對于嚴(yán)格要求眾多瀏覽器兼容性的應(yīng)用,可以通過動態(tài)判斷瀏覽器的類型在 IE 中使用 VML,在其他瀏覽器中使用 SVG。但更推薦直接使用 Raphael 開源類庫。

  • 盡量控制矢量繪圖的使用范圍,使得如果矢量繪圖技術(shù)在本地瀏覽器不可用時(shí),不影響基本功能的使用。例如:利用矢量繪圖繪制報(bào)表圖形,廣告,等等。

小結(jié)

隨著當(dāng)今社會對各種產(chǎn)品和服務(wù)的用戶體驗(yàn)的要求越來越來高,矢量繪圖在 Web 頁面開發(fā)中的重要性與日俱增。本文對當(dāng)前主流的三種 Web 矢量繪圖技術(shù)進(jìn)行了詳細(xì)的介紹。并以開源項(xiàng)目 Raphael 為例介紹了混合矢量繪圖技術(shù)。在此基礎(chǔ)上對 Web 應(yīng)用中如何使用矢量繪圖技術(shù)給出了一些建議。雖然,如本文所述,Web 上的矢量繪圖技術(shù)暫時(shí)還沒有哪一種能成為主導(dǎo),但是隨著技術(shù)的發(fā)展和需求的增強(qiáng),終將會有一、兩種已存在的或新的矢量繪圖技術(shù)脫穎而出并被廣泛接受和使用,把我們的網(wǎng)絡(luò)生活裝扮的更加“豐富多彩”。


本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
瀏覽器繪圖的基本原理
基于HTML5的數(shù)據(jù)可視化方法有哪些
使用 HTML5 canvas 進(jìn)行 Web 繪圖
HTML5-Canvas繪畫
HTML5之SVG 2D入門1
H5_canvas與svg
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服