參考:http://www.html5china.com/HTML5features/canvas/
開始:
- <canvas id="canvas" width="300" height="200">
- Fallback content, in case the browser does not support Canvas.
- </canvas>
需要指明的是,由於無法保證所有用戶使用的瀏覽器都能夠支持 canvas 元素,所以在目前開發基於 canvas 的 Web 應用中需要增加“Fallback content”,以提示用戶他們無法正常體驗此功能的原因或建議他們去下載最新的瀏覽器。
這裏,好奇的讀者可能會問,既然這是一個普通的 DOM 節點,那麼便意味着可以通過直接改變其 width 或 height 屬性值來改變 canvas 的大小?確實如此,但是,正如之前提到的 canvas 是一種像素級別的繪圖方法,因而,一旦動態調整 canvas 的大小,canvas 將被“重置”到一個新的初始狀態,即便是如下這種操作,也會將 canvas 內的位圖清除並將所有相關屬性恢復到初始值的狀態。當然,我們也可以把這當作重置 canvas 的小技巧來使用。
- document.getElementById("canvas").width = document.getElementById("canvas").width;
基於 canvas 的繪圖並不是直接在 canvas 標記所創建的繪圖畫面上進行各種繪圖操作,而是依賴畫面所提供的 渲染上下文(Rendering Context),所有的繪圖命令和屬性都定義在渲染上下文當中。在通過 canvas id 獲取相應的 DOM 對象之後首先要做的事情就是獲取渲染上下文對象。 渲染上下文與 canvas 一一對應,無論對同一 canvas 對象調用幾次 getContext() 方法,都將返回同一個上下文對象。目前,所有支持 canvas 標籤的瀏覽器都支持 2D 渲染上下文,可以使用如下的代碼來獲取該對象。
var context = document.getElementById("canvas").getContext("2d");
除此之外,在不久的將來,開發人員還會能夠得到基於 OpenGL 的 3D 渲染上下文以在 canvas 中進行 3D 繪圖。
與 SVG 不同,canvas 原生支持的基本圖形只有矩形一種,至於其他的圓形,多邊形等圖形則都由路徑來負責繪製實現。清單 1 展示瞭如何使用渲染上下文中的矩形繪圖方法完成了圖 1 所示圖形。
例子及說明:
<!DOCTYPE HTML> <html> <head> <script type="text/javascript"> window. test(){ var canvas = document.getElementById('canvas'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); // 獲取 2D 渲染上下文 ctx.clearRect(0,0,100,200) ;// 清除以(0,0)爲左上座標原點,300*200 矩形區域內所有像素 ctx.fillStyle = '#00f'; // 設置矩形的填充屬性,#00f 代表藍色 ctx.strokeStyle = '#f00'; // 設置矩形的線條顏色,#f00 代表紅色 ctx.fillRect(50,50,150,80); // 使用 fillStyle 填充一個 150*80 大小的矩形 ctx.strokeRect(45,45, 160, 90); // 以 strokeStype 屬性爲邊的顏色繪製一個無填充矩形 } } </script> </head> <body> <canvas id="canvas" style="border:1px solid #c3c3c3;"> Your browser does not support the canvas element. </canvas> </body> </html>
|
在開始動手繪製路徑之前,首先需要明確的是:矩形繪製 API 是一種即時性的 API,他會在相應的繪圖函數執行完畢之後,將圖形即時的渲染在畫面上。然而路徑繪製 API 並非如此,完整的路徑繪製過程大致可以分爲如下兩個階段:
- 定義路徑輪廓:
在每個 canvas 實例對象中都擁有一個 path 對象,創建自定義圖形的過程就是不斷對 path 對象操作的過程。每當開始一次新的圖形繪製任務,都需要先使用 beginPath() 方法來重置 path 對象至初始狀態,進而通過一系列對 moveTo/lineTo 等畫線方法的調用,繪製期望的路徑,其中 moveTo(x, y) 方法設置繪圖起始座標,而 lineTo(x,y) 等畫線方法可以從當前起點繪製直線,圓弧以及曲線到目標位置。最後一步,也是可選的步驟,是調用 closePath() 方法將自定義圖形進行閉合,該方法將自動創建一條從當前座標到起始座標的直線。
- 繪製路徑
定義完路徑的輪廓,此時 canvas 畫面中沒有顯示任何路徑,開發人員還可以對路徑進行修改。一旦確定完成,則需要繼續調用 stroke()/fill() 函數來完成將路徑渲染到畫面的最後一步。路徑的輪廓顏色和填充顏色由 strokeStyle 和 fillStyle 屬性決定
- <!DOCTYPE HTML>
- <html>
- <head>
- <script type="text/javascript">
- window.onload=function test(){
- var canvas = document.getElementById('canvas');
- if (canvas.getContext){
- var ctx = canvas.getContext('2d'); // 獲取 2D 渲染上下文
- ctx.clearRect(0,0,400,500) ;// 清除以(0,0)爲左上座標原點,300*200 矩形區域內所有像素
- ctx.fillStyle = '#00f'; // 設置矩形的填充屬性,#00f 代表藍色
- ctx.strokeStyle = '#f00'; // 設置矩形的線條顏色,#f00 代表紅色
- ctx.fillRect(50,50,150,80); // 使用 fillStyle 填充一個 150*80 大小的矩形
- ctx.strokeRect(45,45, 160, 90); // 以 strokeStype 屬性爲邊的顏色繪製一個無填充矩形
- }
- var canvas2 = document.getElementById('canvas2');
- if (canvas2.getContext){
- var ctx = canvas2.getContext('2d');
- ctx.fillStyle = '#00f';
- ctx.strokeStyle = '#f00';
- ctx.beginPath();
- ctx.arc(75,45,50,0,Math.PI, false); // 繪製一條半圓弧線
- ctx.closePath(); // 自動繪製一條直線來關閉弧線。若不調用此方法,將僅僅顯示一條半圓弧
- ctx.fill(); // 可以嘗試註釋掉 fill 或者 stroke 函數,觀察圖形的變化
- ctx.stroke();
- }
- }
- </script>
- </head>
- <body>
- <canvas id="canvas" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- </canvas>
- <canvas id="canvas2" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- </canvas>
- </body>
- </html>
Canvas 繪圖中另一個重要的概念是 繪畫狀態(Drawing State),繪畫狀態反映了渲染上下文當前的瞬時狀態,開發人員可以通過對繪畫狀態的保存 / 恢復操作而快速的回到之前使用的各種屬性和變形操作。繪畫狀態主要由以下三個部分構成:
- 當前的變形矩陣(transformation matrix)
- 當前的裁剪區域(clipping region)
- 當前上下文中的屬性,比如 strokeStyle, fillType, globalAlpha, font 等等。
需要指出的是,當前路徑對象以及當前的位圖都不包含在繪畫狀態之中,路徑是持續性的對象,如前文所講,只有通過 beginPath() 操作纔會進行重置,而位圖則是 canvas 的屬性,並非屬於渲染上下文的。
開發人員可以使用 save 和 restore 兩種方法來保存和恢復 canvas 狀態,每調用 save 方法,都會將當前狀態壓入堆棧中,而相應的 restore 方法則會從堆棧中彈出一個狀態,並將當前畫面恢復至該狀態。繪畫狀態在 canvas 圖形變形操作中應用極爲廣泛,也非常重要,因爲調用一個 restore 方法遠比手動恢復先前狀態要簡單許多,因而,一個較好的習慣是在做變形操作之前先保存 canvas 狀態。
二維繪圖的常用變形操作在 canvas 中都可到了很好的支持,包括平移(Translate),旋轉(Rotate),伸縮(Scale)等等。由於所有的變形操作都基於變形矩陣,因而開發人員始終需要記住一點的就是,一旦沒有使用 save/restore 操作保持住原來的繪圖狀態,那麼後續的繪圖操作,都會在當前所應用的變形狀態下完成。清單 3 使用平移和旋轉方法繪製瞭如下所示畫面。
- <!DOCTYPE HTML>
- <html>
- <head>
- <script type="text/javascript">
- window.onload=function test(){
- var canvas = document.getElementById('canvas');
- if (canvas.getContext){
- var ctx = canvas.getContext('2d'); // 獲取 2D 渲染上下文
- ctx.clearRect(0,0,400,500) ;// 清除以(0,0)爲左上座標原點,300*200 矩形區域內所有像素
- ctx.fillStyle = '#00f'; // 設置矩形的填充屬性,#00f 代表藍色
- ctx.strokeStyle = '#f00'; // 設置矩形的線條顏色,#f00 代表紅色
- ctx.fillRect(50,50,150,80); // 使用 fillStyle 填充一個 150*80 大小的矩形
- ctx.strokeRect(45,45, 160, 90); // 以 strokeStype 屬性爲邊的顏色繪製一個無填充矩形
- }
- var canvas2 = document.getElementById('canvas2');
- if (canvas2.getContext){
- var ctx = canvas2.getContext('2d');
- ctx.fillStyle = '#00f';
- ctx.strokeStyle = '#f00';
- ctx.beginPath();
- ctx.arc(75,45,50,0,Math.PI, false); // 繪製一條半圓弧線
- ctx.closePath(); // 自動繪製一條直線來關閉弧線。若不調用此方法,將僅僅顯示一條半圓弧
- ctx.fill(); // 可以嘗試註釋掉 fill 或者 stroke 函數,觀察圖形的變化
- ctx.stroke();
- }
- var canvas3 = document.getElementById('canvas3');
- if (canvas3.getContext){
- var ctx = canvas3.getContext('2d');
- ctx.translate(150,80); // 將 canvas 的原點從 (0,0) 平移至(150,150)
- for (i=1;i<=2;i++){ // 繪製內外 2 層
- if ((i % 2) == 1) {ctx.fillStyle = '#00f';}
- else{ ctx.fillStyle = '#f00'; }
- ctx.save(); // 保持開始繪製每一層時的狀態一致
- for (j=0;j<=i*6;j++){ // 每層生成點的數量
- ctx.rotate(Math.PI/(3*i)); // 繞當前原點將座標系順時針旋轉 Math.Pi/(3*i) 度
- ctx.beginPath();
- ctx.arc(0,20*i,5,0,Math.PI*2,true);
- ctx.fill(); // 使用 fillType 值填充每個點
- }
- ctx.restore();
- }
- }
- }
- </script>
- </head>
- <body>
- <canvas id="canvas" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- </canvas>
- <canvas id="canvas2" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- </canvas>
- <canvas id="canvas3" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- </canvas>
- </body>
- </html>