- WebGL 3D開發實戰詳解(第2版)
- 吳亞峰 于復興 索依娜
- 3528字
- 2020-07-07 17:17:04
1.6 HTML5 Canvas簡介
HTML5 Canvas是屏幕上由JavaScript控制的即時模式位圖區域。即時模式是指在畫布上呈現像素的方式,HTML Canvas通過JavaScript調用Canvas API,在每一幀中完全重繪屏幕上的位圖。開人員需要做的就是在每一幀渲染之前設置屏幕的內容顯示。
1.6.1 文檔對象模型和Canvas
文檔對象模型(DOM)代表了HTML頁面上的所有對象,它是語言中立且平臺中立的。它允許頁面的內容和樣式被Web瀏覽器渲染之后再次更新。用戶可以通過JavaScript訪問DOM。現在DOM已經成為JavaScript、DHTML和CSS開發中最重要的一部分。
畫布元素本身可以通過DOM在Web瀏覽器中經由Canvas 2D環境訪問。但是,在Canvas中創建的單個圖形元素是不能通過DOM來訪問的。正如本章前面講到的,畫布工作在即時模式,它并不保存自己的對象,只是說明在單個幀里繪制什么。
? 在使用Canvas之前大家需要了解兩個DOM對象,其中一個對象為document,它包含所有在HTML頁面的HTML標簽上。
? 另一個對象window是DOM的最高一級,需要檢測這個對象來確保在開始使用Canvas應用程序之前,已經加載了所有的資源和代碼。
1.6.2 JavaScript與Canvas
用JavaScript來創建Canvas應用程序,程序能在現有的任何Web瀏覽器中運行。在使用JavaScript為Canvas編程時會有一個問題,在創建的頁面中哪里為JavaScript程序的起點?有兩種方式,一種為放在<head>標簽中,另一種為放在<body>標簽中。
? 將起點放在<head>元素中意味著整個HTML頁面要加載完JavaScript才能配合HTML運行,在運行該程序前就必須檢查HTML頁面是否已經加載完畢。
? 另一種將起點放在<body>元素內的好處是,它可確保JavaScript運行時整個頁面已經加載完畢。由于在運行Canvas程序前需要使用JavaScript測試頁面是否加載,所以兩種方法各有利弊。本書在編寫的時候用的是第二種,讀者可以選擇自己喜歡的方式進行編程。
1.6.3 HTML5 Canvas版“Hello World”
現在來開發Canvas之路上的第一個案例,即Canvas版的“Hello World”。本節將從開發程序的第一步開始,一步步地將程序開發的過程呈現給大家,讓沒有開發經驗的讀者對開發程序有一個整體的概念。
在上一節中講到了JavaScript與Canvas的關系。由于在開發本部分內容時html文件中難免會嵌入JavaScript腳本,所以我們第一步來看一下如何將JavaScript程序中的方法封裝起來,并留下JavaScript程序的入口。
1.封裝JavaScript代碼
Canvas應用程序與瀏覽器中運行的其他應用有所不同。由于Canvas只在屏幕上的特定區域內執行并顯示結果,可以說它的功能是獨占的,因此不太會受到頁面上其他內容的影響,反之亦然。讀者如果想在同一個頁面上放置多個Canvas應用,那么在定義時必須將對應代碼分開。
為了避免出現這個問題,可以將變量和函數都封裝在另一個函數中。JavaScript函數本身就是對象,JavaScript對象既可以有屬性也可以有方法。將一個函數放到另一個函數中,讀者可以使第二個函數只在第一個函數的局部作用域中。
1 function eventWindowLoaded(){canvasApp(); } //JavaScript程序在Canvas中的入口函數 2 function canvasApp(){ //入口函數需要調用的函數 3 drawScreen(); //繪制場景函數 4 …… 5 function drawScreen(){…… //繪制函數,本程序中的重點 6 }}
上述代碼講解了如何將JavaScript代碼封裝起來,封裝好的方法只留下eventWindowLoaded()方法。在下一節中還將繪制不同圖形的方法并放到外部文件中,在<head>標簽部分加載這些文件,待到需要繪制時直接調用相應的方法即可。
2.將Canvas添加到HTML頁面中
在HTML的<body>標簽中添加一個<Canvas>標簽時,可以參考下述代碼。<canvas>標簽有3個主要屬性。大家都知道在HTML中,屬性被設置在相應的標簽中,id、width、height這3個屬性分別代表JavaScript代碼中用來指示特定<canvas>標簽的名字、畫布的寬度與高度。
1 <canvas id="canvasOne" width="500" height="300"> 2 若看到這個文字,則說明瀏覽器不支持WebGL! </canvas>
在開始標簽和結束標簽中可以添加文本,一旦瀏覽器在執行HTML頁面時不支持Canvas,就會顯示這些文字。以本章的Canvas應用程序為例,這里使用的是“若看到這個文字,則說明瀏覽器不支持WebGL”。事實上此處可以隨意放置文字。
接下來用DOM引用HTML中定義的<canvas>標簽。document對象加載后可以引用HTML頁面的任何元素。需要一個Canvas對象的引用,這樣就能夠知道當JavaScript調用Canvas API時其結果在哪里顯示了。
var theCanvas=document.getElementById("canvasOne");
首先定義一個名為theCanvas的新變量,以保存Canvas對象的引用。接下來,通過調用document的getElementById()函數得到canvasOne的引用。canvasOne是在HTML頁面中為創建的<canvas>標簽定義的名字。
3.檢測瀏覽器是否支持Canvas
現在已經得到了在HTML頁面上定義的Canvas元素的引用,下面檢測它是否包含環境。Canvas環境是指支持由Canvas的瀏覽器定義的繪圖界面。簡單地說,如果環境不存在,那么畫布也不會存在。有多種方式可以對此進行驗證。
這里使用的是modernizr.js庫中的Modernizr,它是一個易用并且輕量級的庫,可以檢測各種Web技術的支持情況。Modernizr創建一組靜態的布爾值,可以檢測是否支持Canvas。在程序中已經包含modernizr.js,讀者不用再自行下載了。
1 <script src="modernizr.js"></script> 2 function canvasSupport(){ 3 return Modernizr.canvas; }
上面代碼第1行為將外部.js文件導入到HTML文件中,下面的代碼是為了檢測是否支持Canvas,而將canvasSupport()函數進行修改。這里將要使用modernizr.js方法,因此它提供了測試Web瀏覽器是否支持Canvas的最佳途徑。
4.獲得2D環境
var context =theCanvas.getContext("2d");
最后需要得到2D環境的引用才能操作它。HTML5 Canvas被設計為可以與多個環境工作,包含一個建議的3D環境。不過這里只用到了2D環境。通過getContex()方法取得context,然后在之后的繪制函數中大家便可以用context來設置各個屬性了。
5.繪制函數
現在可以創建實際的Canvas API代碼了。在Canvas上運行的各種操作都要通過context對象,因為它引用了HTML頁面上的對象。大家在案例中所看見的“屏幕”就是定義畫布的繪圖區域。首先應清空繪圖區域。
1 context.fillStyle="#ffffaa"; 2 context.fillRect(0,0,500,300);
上面的兩行代碼在屏幕上繪制出一個與畫布大小相同的黃色方塊。fillStyle()設置顏色,fillRect()創建一個矩形,并把它放到了屏幕上。在清空完繪圖區域后,看一下繪制函數drawScreen()是如何開發的。
1 function drawScreen(){ 2 context.fillStyle="#ffffaa"; //背景 3 context.fillRect(0,0,500,300); //創建一個矩形 4 context.fillStyle="#000000"; //文字 5 context.font="20px Sans-Serif"; //設置字體的大小和字號 6 context.textBaseline="top"; //設置字體的垂直對齊方式 7 context.fillText("Hello World! ",195,80); //將測試文本顯示到屏幕上 8 var helloWorldImage=new Image(); //添加2D圖像 9 helloWorldImage.onload=function(){ 10 context.drawImage(helloWorldImage,155,110); } 11 helloWorldImage.src="pic/helloworld.png"; 12 context.strokeStyle="#000000"; //設置邊框 13 context.strokeRect(5,5,490,290); 14 }
? 第2~7行設置了背景顏色與形狀,之后聲明了文字的顏色、大小和字號并設置了字體的垂直對齊方式,最后將測試文本顯示到屏幕上。
? 第8~13行為添加圖形。為了將圖像顯示到畫布上,需要創建一個Image()對象實例,并且將Image.src屬性設為將要加載的圖像名字。在顯示圖像之前,需要等待圖像加載完畢。設置Image對象的onload函數可以為Imageload創建一個回調函數。
由于上面幾節已將本例中的重點代碼介紹了,所以就不再將全部代碼在這里重寫一遍了,讀者可以查閱隨書資源中的Sample1_23案例進行學習。下面來看一下第一個Canvas程序的運行效果,如圖1-23所示。

圖1-23 案例Sample1_23效果
讀者在第一次開發時肯定會遇到一些問題,還會有調試程序的步驟。但是這里不會將可能的錯誤全部羅列出,讀者在開發中遇到問題時可以用前面提到的瀏覽器自帶調試器或者firebug進行調試。
學完Canvas版“Hello World”的開發過程后,大家來進一步深入學習一下Canvas提供的一些繪制基本圖形的API。看完這些內容后讀者就可以開發一些2D的內容了,這里提供的為系統的API,讀者只要認真學習都可以掌握。
1.6.4 Canvas中的基礎圖形
在看完第一個Canvas程序后大家對它已有了基本認識,HTML5 Canvas的使用是以強大的繪圖、著色和基本二維形狀變換為基礎的。然而,可供選擇的內建形狀相對有限,程序員可以通過一組稱作路徑的線段來繪制出想要的形狀。
現在學習一下新的內容,在Canvas上繪制一些基本圖形。繪制這些圖形基本上都會有相應的API,本案例中不同的圖形會在不同的JavaScript文件中,相應的API在里邊都會有所體現。讀者閱讀時結合著注釋便能夠輕松學會,現在看一下這部分的開發過程。
代碼位置:隨書源代碼/第1章目錄下的HTML5/Sample1_24.html。
1 <! DOCTYPE HTML> 2 <html><head><title>Sample1_24</title> 3 <script src="js/modernizr.js"></script> //導入js文件夾下的modernizr.js文件 4 <script src="js/arc.js"></script> //導入js文件夾下的arc.js文件 5 <script src="js/bezier.js"></script> //導入js文件夾下的bezier.js文件 6 <script src="js/line.js"></script> //導入js文件夾下的line.js文件 7 <script src="js/linejoin.js"></script> //導入js文件夾下的linejoin.js文件 8 <script src="js/rect.js"></script> //導入js文件夾下的rect.js文件 9 <script type="text/javascript"> //前面導入的為外部JavaScript文件, 這里為內嵌的JavaScript文件 10 var context; 11 function eventWindowLoaded(){canvasApp(); } //封裝加載JavaScript的方法 12 function canvasSupport(){ //檢測瀏覽器版本是否支持Canvas 13 return Modernizr.canvas; } 14 function canvasApp(){ //實際JavaScript的入口方法 15 if(! canvasSupport()){return; }else{ 16 var theCanvas = document.getElementById("canvas"); 17 context=theCanvas.getContext("2d"); } 18 drawScreen(); //繪制場景,不同的圖形有不同的繪制方法,這里省略了其余的方法 19 function drawScreen(){ //繪制2D圖形的方法 20 //畫布背景色為白色,這不利于辨識,填充一個有顏色的區域便于標識 21 context.fillStyle="#aaaaaa"; //設置背景樣式 22 context.fillRect(0,0,500,500); //創建一個矩形 23 context.fillStyle='#000000'; //文字 24 context.font='20px _sans'; //文字的大小和字號 25 context.textBaseline='top'; //設置文本垂直對齊方式 26 context.fillText("Canvas! ",0,0); }} //將測試文本顯示到屏幕上 27 </script></head> 28 <body onload="eventWindowLoaded(); "> 29 <div style="position: absolute; top: 50px; left:50px; "> 30 <canvas id="canvas" width="500" height="500"> 31 若看到這個文字,則說明瀏覽器不支持WebGL! </canvas></div> 32 </body></html>
? 第2~8行引入了各圖形的JavaScript文件。每個圖形的繪制方法都封裝在了不同的文件中,在繪制時調用不同的繪制方法即可。讀者在測試本案例時只需將drawScreen()方法替換掉便能測試不同的圖形了。
? 第9~26行為內嵌的JavaScript腳本。這部分是Canvas程序的入口,其中Canvas的id通過context來設置一些屬性,并且將繪圖區域清屏并設置了一個與畫布等大的矩形以顯示Canvas畫布。
? 第28~32行為創建Canvas的過程。具體過程在前面幾節中已分別介紹了,onload在頁面加載完畢后調用JavaScript腳本,Canvas設置好其3個屬性。
在程序中調用drawScreen()方法時需要注意的是,在程序開頭導入的幾個JavaScript文件,這些文件包含繪制圓、直線、曲線的一些圖形API,讀者可以自行查閱這些代碼進行學習,其中的解釋和注意事項在注釋中都有詳細介紹,這里便不再贅述。
HTML5 Canvas這里便介紹完畢,讀者千萬別以為就已經掌握了Canvas, Canvas是HTML5新增的元素,可以干的事情還有很多。本章只介紹了2D環境下的繪制圖形,以后的章節才是Canvas的真正應用。