畫布 2D 網頁應用/HTML 網頁應用
本章討論使用單個畫布元素進行渲染的 HTML 網頁的基本結構。討論包括最重要的渲染命令。假設讀者熟悉 JavaScript(或 ECMAScript)。
以下 HTML 程式碼使用畫布元素繪製一些文字和來自維基共享資源的影像。您應該使用您喜歡的文字編輯器建立一個新檔案,將程式碼複製貼上到其中,然後將檔案儲存到您的計算機上(最好使用“.html”副檔名)。然後使用您喜歡的網頁瀏覽器開啟該檔案。(或者,它也可以在網上獲得。)它應該在淺藍色背景上顯示 HTML5 圖示上的“Hello, world!”文字。下面我們將詳細討論該示例。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<script>
var myImage = new Image();
function init() {
myImage.onload = update; // call update when image is loaded
myImage.src = "http://upload.wikimedia.org/wikipedia/" +
"commons/thumb/2/25/HTML5_Shiny_Icon.svg/" +
"200px-HTML5_Shiny_Icon.svg.png";
}
function update() {
// get canvas and context
var myCanvas = document.getElementById("mycanvas");
var myContext = myCanvas.getContext("2d");
// set canvas size to window size
myCanvas.width = window.innerWidth;
myCanvas.height = window.innerHeight;
// clear context to transparent black
myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
// render in front-to-back order
myContext.globalCompositeOperation = "destination-over";
// write some text in black
myContext.fillStyle = "#000000";
myContext.font = "bold 48px Helvetica, sans-serif";
myContext.textAlign = "center";
myContext.textBaseline = "middle";
myContext.fillText("Hello, world!", 170, 60);
// draw the image (behind the text)
myContext.drawImage(myImage, 10, 20, 50, 51);
// fill the background of the canvas with light blue
myContext.fillStyle = "#C0C0FF";
myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
}
</script>
</head>
<body bgcolor="#000000" onload="init()" onresize="update()">
<canvas width="400" height="300" id="mycanvas"
style="position:absolute; left:0px; top:0px; "></canvas>
</body>
</html>
如果您的網頁瀏覽器無法正確顯示網頁,您應該嘗試使用網頁瀏覽器的開發者工具和錯誤訊息列表來除錯網頁。不幸的是,如何開啟這些工具取決於瀏覽器;因此,您必須檢視您的網頁瀏覽器的文件。
如果您更改了程式碼,請記住在您重新載入網頁瀏覽器中的頁面之前儲存它。但是,某些瀏覽器可能會使用快取版本而不是包含您更改的新版本。處理此問題的最安全方法是將新版本儲存為一個新名稱,並在網頁瀏覽器中開啟此新檔案。
在本節中,將詳細討論示例中的所有程式碼。程式碼從一些 HTML 文字開始
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
...
這只是標準 HTML 程式碼來啟動一個網頁。meta 標籤被包含進來,以避免有關未指定字元集的警告。
以下部分是包含 JavaScript 程式碼的script元素,我們現在跳過它。最後部分再次是 HTML 程式碼
...
</head>
<body bgcolor="#000000" onload="init()" onresize="update()">
<canvas width="400" height="300" id="mycanvas"
style="position:absolute; left:0px; top:0px; "></canvas>
</body>
</html>
body標籤指定了網頁的內容。屬性bgcolor="#000000"將背景顏色設定為黑色(如果它曾經可見)。屬性onload="init()"指定了網頁瀏覽器應該在網頁載入後執行init函式(我們將在下面討論)。onresize="update()"指定了只要瀏覽器視窗大小調整,就應該呼叫update函式(我們也將在下面討論)。
在此網頁中,網頁主體中只有一個canvas元素。屬性width和height分別以 CSS 畫素指定畫布元素的寬度和高度(這可能與物理裝置畫素不同;例如,一個 CSS 畫素通常對應於某些 iOS 裝置視網膜顯示屏上的 2×2 裝置畫素)。但是,畫布元素的大小可以在 JavaScript 程式碼中更改,如以下所述。屬性id="mycanvas"為畫布元素指定一個 ID,以便它可以在 JavaScript 程式碼中識別。(如果有多個畫布元素,這將特別有用。)最後,style="position:absolute; left:0px; top:0px; "將畫布的左上角放置在網頁的左上角,沒有任何邊距,這對於我們希望畫布填充整個瀏覽器視窗非常重要。
在此示例中,canvas元素為空,即在<canvas>和</canvas>之間沒有指定任何內容。如果在這些標籤之間存在任何 HTML 元素,它們將被顯示,如果網頁瀏覽器不支援渲染到canvas元素中。
script元素定義了此網頁的所有 JavaScript 程式碼。第一部分定義了一個全域性變數myImage,它被初始化為一個新的空影像,以及函式init,它在網頁瀏覽器載入網頁主體後被呼叫(見上文)。
...
<script>
var myImage = new Image();
function init() {
myImage.onload = update; // call update when image is loaded
myImage.src = "http://upload.wikimedia.org/wikipedia/" +
"commons/thumb/2/25/HTML5_Shiny_Icon.svg/" +
"200px-HTML5_Shiny_Icon.svg.png";
}
...
行myImage.onload = update指定了函式update(見下文)應該在影像載入後被呼叫。下一行myImage.src = "http://...";指定了應該從哪裡載入影像的 URL 地址。該字串也可以指定相對於 HTML 檔案位置的影像檔案的路徑名。
第二個函式稱為update,因為它更新畫布元素的內容。
...
function update() {
// get canvas and context
var myCanvas = document.getElementById("mycanvas");
var myContext = myCanvas.getContext("2d");
// set canvas size to window size
myCanvas.width = window.innerWidth;
myCanvas.height = window.innerHeight;
// clear context to transparent black
myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
// render in front-to-back order
myContext.globalCompositeOperation = "destination-over";
// write some text in black
myContext.fillStyle = "#000000";
myContext.font = "bold 48px Helvetica, sans-serif";
myContext.textAlign = "center";
myContext.textBaseline = "middle";
myContext.fillText("Hello, world!", 170, 60);
// draw the image (behind the text)
myContext.drawImage(myImage, 10, 20, 50, 51);
// fill the background of the canvas with light blue
myContext.fillStyle = "#C0C0FF";
myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
}
</script>
...
首先,使用document.getElementByID("mycanvas")檢索畫布元素(有關畫布元素的 ID 的定義,請參見上文),並將其分配給變數myCanvas。對於此畫布,使用myCanvas.getContext("2d")檢索“畫布 2D 上下文”,並將其分配給變數myContext。本華夏公益教科書中討論的所有渲染函式都使用 2D 上下文。
2D 上下文的大小由相應的畫布指定。在此示例中,行myCanvas.width = window.innerWidth;和myCanvas.height = window.innerHeight;將畫布(以及 2D 上下文)的大小設定為瀏覽器視窗的大小。由於只要瀏覽器視窗大小調整就會呼叫update函式(見上文關於body元素的討論),因此畫布及其上下文始終設定為瀏覽器視窗的大小。
行myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);將整個上下文清除為透明黑色。(更改畫布的大小通常也會清除上下文;因此,此行通常不是必需的。)
行myContext.globalCompositeOperation = "destination-over";指定了適合從前到後渲染的合成操作;即,最前面的元素(遮擋所有其他元素的元素)首先渲染,然後遮擋除最前面元素之外所有元素的元素,依此類推。因此,背景必須最後渲染。這與我們在傳統反向玻璃畫中使用的方式相同。從前到後的渲染在計算機圖形學中有點不尋常,但我們在本華夏公益教科書中使用它,因為它與我們處理滑鼠和觸控事件的方式一致。
行myContext.fillStyle = "#000000";指定了以下命令應該使用黑色作為填充顏色。myContext.font = "bold 48px Helvetica, sans-serif";指定了以下命令應該使用 48 畫素粗體 Helvetica 字型或預設無襯線字型(如果 Helvetica 不可使用)。行myContext.textAlign = "center";和myContext.textBaseline = "middle";將垂直和水平對齊設定為居中;即,文字將以指定錨點為中心。行myContext.fillText("Hello, world!", 170, 60);然後使用已在先前行中指定的字型和填充顏色,以 x 座標 170 和 y 座標 60(座標系的原點在畫布的左上角)為中心編寫字串"Hello, world!"。
下一行myContext.drawImage(myImage, 10, 20, 50, 51);繪製圖像myImage,其左上角在 x 座標 10 和 y 座標 20 處,並將其重新縮放為 50 畫素的寬度和 51 畫素的高度。如果最後兩個引數被跳過(即對於myContext.drawImage(myImage, 10, 20);),則將使用myImage的原始寬度和高度;因此,影像將不會被重新縮放。
類似於之前的一行,myContext.fillStyle = "#C0C0FF";指定填充顏色;在本例中,它是淺藍色。(紅色和綠色強度由 C0 指定,它是值 192 的十六進位制程式碼,藍色強度由 FF 指定,它是值 255 的十六進位制程式碼,即最大強度。)行myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);繪製一個填充矩形,其左上角在 x 座標 0 和 y 座標 0(即畫布的左上角)處,寬度為myCanvas.width,高度為myCanvas.height。因此,矩形覆蓋了整個畫布。
這結束了對示例的討論。為了熟悉程式碼和函式,強烈建議您進行練習;例如,透過更改顏色和字型,更改位置和大小,替換影像或新增其他影像、矩形或文字等。
畫布元素的 2D 上下文中還有更多用於渲染的功能。它們都在全球資訊網聯盟 (W3C) 的文件“HTML Canvas 2D 上下文” 中進行了說明。但是,出於以下兩個原因,我們不會在本華夏公益教科書中討論更多這些功能。
- 對於大多數互動式網頁和 Web 應用程式的原型,所討論的功能就足夠了。
- 如果網頁或 Web 應用程式的最終版本由專業的網頁設計師設計,他或她通常更喜歡將圖形元素建立為點陣圖影像,這些影像可以使用上面討論的
drawImage函式進行渲染。
顯然,在某些情況下,更多渲染功能是有用的,鼓勵讀者在這些情況下閱讀 W3C 提供的 2D 上下文規範。