HTML 5新特性Canvas入門秘籍
隨著IE 10的即將發布正式版,標志者HTML5的時代已經越來離我們越來越近了,盡管HTML 5的最終標準草案還沒最終敲定,但象Chrome,Firefox等瀏覽器對HTML5的標準已經支持的十分完善了,IE 10的預覽版本也聲稱支持更多的HTML 5特性。在此情況下,無論作為CTO還是一般的前端頁面開發者還是網站編程的開發人員,都應該開始給予HTML5相當的重視。而在HTML5中,其中最令開發者和用戶值得留意的新特性,莫過于Canvas的功能了,它能在目前的IE 9,IE 10以及Chrome,FireFox等多種瀏覽器中使用,是目前HTML5中富客戶端動畫效果的實現方式,有了它,HTML5就有了跟Adobe Flash對抗的資本,用戶以后只要使用支持HTML5的瀏覽器,就可以不用安裝Flash插件了。那么,究竟什么是HTML 5中的Canvas功能呢?本文將帶領初學者學習Canvas的入門知識。
51CTO推薦專題:HTML 5 下一代Web開發標準詳解
走近Canvas 元素標簽
官方對Canvas元素標簽的定義為:Canvas(畫布)可以用來進行繪制圖形,繪制游戲的圖案或者其他圖形圖案,允許使用腳本動態渲染點陣圖像。簡單來說,Canvas就是允許你在HTML5中,使用Javascript去繪制你喜歡的任何圖形了,包括文字,圖片、線、點、各種形狀等。Canvas使用的是Canvas 2D API去繪制圖形的,這個API功能十分強大,而且大部分的瀏覽器都支持 2D canvas ——包括 Opera, Firefox, Konqueror 和 Safari。而且某些版本的 Opera 還支持 3D canvas ,firefox 也可以通過插件形式支持 3D canvas 。下面馬上來看Canvas的例子。
- <canvas id=”myCanvas” style=”width:300px; height:300px”></canvas>
這個代碼就會在瀏覽器中先繪畫一張畫布,寬度和高度都是300px,但這個時候頁面上并不能顯示什么效果,只是一個空的區域。
在一個頁面中,可以有不同的canvas,不同的canvas都必須有自己的id屬性以示區分。為了在canvas上繪制圖形,必須引用canvas的上下文context變量。Context上下文能讓你訪問2D API中的屬性和方法,這樣就可以在畫布元素中操作和繪畫圖形了,這個我們稍后再詳細講解。
先來看下每一canvas元素標簽中都有X和Y坐標,X坐標代表水平,Y坐標代表垂直,下圖是其坐標系的圖:

Canvas和SVG的關系
開發者必須清楚SVG技術和canvas是不同的。SVG是基于XML的圖形矢量顯示技術,可以將其與CSS混搭使用,也可以使用SVG DOM動態向其添加行為。而canvas則允許使用Javascript去繪制各種圖象和圖形,下面是一些canvas勝過svg的優點:
1) canvas在繪制復雜圖象時,繪畫速度比SVG快不少。
2) 可以保存canvas繪制的圖象,但SVG不能直接使用瀏覽器的保存功能保存。
3) 在canvas中所有東西都以象素形式存在。
4) svg需要在瀏覽器中使用插件顯示。
但要同時注意到,svg也有自身的優勢,比如:
1) svg的圖形解析分辨率能適應不同大小尺寸。
2) svg由于使用XML,因此能定義很多不同的目標元素。
3) svg能繪制很復雜的動畫效果。
那如何選擇呢?建議如果你的網站的圖象對分辨率要求高(矢量圖要求),那么選擇SVG,如果你的應用是網頁游戲等對速度要求響應高的,也不想過多跟XML打交道的話,則選用canvas。更多關于如何選擇SVG和Canvas,可以參考這篇文章的論述:http://blogs.msdn.com/b/ie/archive/2011/04/22/thoughts-on-when-to-use-canvas-and-svg.aspx
Canvas和硬件加速
在學習canvas時,建議讀者閱讀這篇文章《硬件加速下的圖形顯示對比》,這篇文章中對比了HTML5下canvas在各瀏覽器下的渲染表現。在早期的瀏覽器中,所有對圖形的顯示運算都是有CPU去實現的,而隨著互聯網的快速發展,對圖形處理的要求越來越高,于是很多的圖形渲染工作都由圖形處理單元(GPU)去處理了,比如使用Direct2D或者DirectWrite。當圖形處理工作大部分交由GPU去處理時,大大減輕了CPU的工作負擔,可以騰出來做其他更復雜的工作。
Javascript一直被指責在處理圖形方面遜色,但隨著FireFox,Chrome等瀏覽器的大行其道,還有IE 9的新的Javascript引擎Chara,它采用在后臺與IE并行并且獨立的CPU內核中編譯 JavaScript 腳本,采用單獨的后臺線程進行編譯。采用這種方法,可以充分利用現在的多核處理器功能。開發人員可以不用更改任何現有的代碼即可利用現有計算機硬件的帶來的性能提升。
因此,有了瀏覽器在GPU方面的加速功能,就能為HTML5的canvas的使用提供很好的環境。
當向canvas發出繪畫命令時,瀏覽器直接將指令發到圖形加速器而不需要開發者更多的干預,硬件圖形加速器則以難以置信的運算速度實時繪畫和渲染圖形。可以通過閱讀下文來了解更多的在不同瀏覽器之間的硬件加速測試的具體情況(地址:http://ie.microsoft.com/testdrive/Performance/Paintball/Default.html)
Canvas 2D API
canvas 2D API對象允許開發者繪制各種圖片和圖形。調用時,需要通過getContext方法獲得其上下文,這個方法中有一個參數,目前是2d,調用的代碼如下:
- var myCanvas = document.getElementById(“myCanvas”);
- var context = myCanvas.getContext(“2d”);
由于每一個canvas元素都有自己的上下文context,因此如果一個頁面中有多個canvas的話,必須對每一個canvas都按上面的方法獲得其context。除此之外,canvas api有如下的若干重要方法:
形狀變換類的方法
◆ scale –允許對當前canvas對象進行形狀大小變換
◆ rotate –允許對當前的canvas對象繞 x軸和y軸旋轉。
狀態變換類方法
◆ save – 保存當前canvas的狀態
◆ restore –恢復上一個已保存的canvas的狀態
文字類方法
◆ font –設置或獲得當前canvas的字體
◆ fillText –向當前canvas填充文字
◆ measureText –獲得指定文字的寬度
更多的關于canvas 2D API的用法,可以參考這個頁面http://msdn.microsoft.com/en-us/library/ff975057.aspx)。下面,我們開始學習如何使用這些API去繪制圖形。
#p#
繪制形狀和顏色
首先,學習下如何畫矩形,下面是相關的方法:
1) fillRect(x, y, w, h),使用當前樣式去繪制一個矩形并對其進行填充,其中x,y,w,h分別是X,Y坐標和寬度高度坐標。
2)strokeRect(x, y, w, h),使用當前的輪廓樣式去勾畫一個矩形,注意這里是用線條去勾畫,而不是去填充一個矩形。
3)clearRect(x, y, w, h),在當前的畫布中清除矩形的內容。
畫矩形最簡單的方法是用fillRect方法了,如下代碼:
- var canvas = document.getElementById(“myCanvas”);
- var context = canvas.getContext(“2d”);
- context.fillRect(5, 5, 145, 145);
則在X=5,Y=5的坐標系中畫出一個145*145的矩形,如下圖:

如果不指定顏色,默認的是使用黑色去填充整個矩形。可以使用fillStyle方法為矩形指定顏色或其他樣式,比如可以充分利用CSS 3中的opacity透明度屬性,比如如下的代碼,分別畫了三個矩形,每個矩形的下半部分都使用了樣式形成了半透明效果:
- context.fillRect(5, 5, 145, 145);
- context.fillStyle = “rgb(0, 162, 232)”;
- context.fillRect(40, 55, 145, 145);
- context.fillStyle = “rgba(255, 0, 0, 0.2)”;
- context.fillRect(75, 105, 145, 145);
其中rgba中比傳統的rgb多了a,即透明度的含義,a的值也是0到1之間的數字,0表示完全透明,1則是完全不透明。運行結果如下圖:

接下來學習如何繪制圓(弧),繪制用到的方法如下:
- arc(x, y, radius, startAngle, endAngle, anticlockwise)
畫圓或者圓弧。x,y為圓心坐標,radius為半徑,startAngle,endAngle為開始/結束劃圓的角度,anticlockwise為是否逆時針畫圓(True為逆時針,False為順時針)。
注意這里的角度為弧度制,所以如果畫一個正圓的話,是Math.PI * 2,而畫60°的話,就是60 * Math.PI / 180,比如下面的代碼,用fill樣式填充了一個黑色的正圓:
- context.beginPath();
- context.fillStyle = “rgb(0, 0, 0)”;
- context.arc(123, 93, 70, 0, 2 * Math.PI, true);
- context.fill();
如果要用stroke筆來勾畫圓形的話,只需要指定勾畫的樣式strokeStyle即可,如下代碼:
- context.beginPath();
- context.strokeStyle = “rgb(0, 0, 0)”;
- context.arc(123, 93, 70, 0, 2 * Math.PI, true);
- context.stroke();
下面是一個畫弧度的代碼例子:
- context.beginPath();
- context.strokeStyle = “rgb(0, 0, 0)”;
- context.arc(123, 93, 70, 0, 0.5 * Math.PI, true);
- context.stroke();
結果如下圖:

接下來,我們學習如何畫貝塞爾曲線。HTML 5的API中,有一個畫這個曲線的很容易的方法bezierCurveTo,相關參數介紹如下:
bezierCurveTo (cp1x, cp1y, cp2x, cp2y, x, y):為一個畫布的當前子路徑添加一條三次貝塞爾曲線。這條曲線的開始點是畫布的當前點,而結束點是 (x, y)。兩條貝塞爾曲線控制點 (cpX1, cpY1) 和 (cpX2, cpY2) 定義了曲線的形狀。當這個方法返回的時候,當前的位置為 (x, y)。下面是相關代碼:
- context.lineWidth = 20;
- context.beginPath();
- context.moveTo(5, 50);
- context.bezierCurveTo(30, 30, 130, 530, 200, 100);
- context.stroke();
繪畫的圖形如下圖:

由于有了貝塞爾曲線功能的,因此可以繪制很多不同的圖形了,比如下面的代碼繪制出一個簡單的笑臉圖。
- // 繪畫臉部輪廓
- context.beginPath();
- context.lineWidth = 10;
- context.strokeStyle = “rgb(0, 0, 0)”;
- context.arc(200, 233, 150, 0, 2 * Math.PI, true);
- context.stroke();
- // 填充面部顏色
- context.beginPath();
- context.fillStyle = “rgba(80, 100, 80, 0.4)”;
- context.arc(200, 233, 150, 0, 2 * Math.PI, true);
- context.fill();
- // 繪制右眼
- context.lineWidth = 20;
- context.beginPath();
- context.moveTo(230, 130);
- context.bezierCurveTo(230, 130, 230, 130, 240, 200);
- context.stroke();
- // 繪制左眼
- context.beginPath();
- context.moveTo(170, 130);
- context.bezierCurveTo(170, 130, 170, 130, 160, 200);
- context.stroke();
- // 繪制上唇
- context.beginPath();
- context.moveTo(100, 230);
- context.bezierCurveTo(100, 230, 200, 380, 300, 230);
- context.stroke();
- // 繪制下唇
- context.beginPath();
- context.moveTo(100, 235);
- context.bezierCurveTo(105, 270, 200, 480, 300, 232);
- context.stroke();
顯示結果如下圖:

目前為止,我們使用的fillStyle都是使用一種單獨的顏色去填充圖形,而實際上,fillStyle也支持使用多種顏色去填充,比如下面的例子,隨機生成了各種顏色去填充畫布實現了彩虹的效果:
- var a = 1;
- for (j = 0; j < 100; j++) {
- var r = 255, g = 0, b = 0;
- for (i = 0; i < 150; i++) {
- // 黃色
- if (i < 25) g += 10.2;
- // 綠色
- else if (i >= 25 && i < 50) r -= 10.2;
- // 藍色
- else if (i >= 50 && i < 75) {
- g -= 10.2;
- b += 10.2;
- }
- // 紫色
- else if (i >= 75 && i < 100) r += 10.2;
- // 紅色
- else b -= 10.2;
- context.fillStyle = “rgba(” + Math.floor(r) + “,” +
- Math.floor(g) + “,” + Math.floor(b) + “,” + a + “)”;
- context.fillRect(3 * i, 5 * j, 3, 5); } a -= 0.01; }
如果不想使用以上的方法去生成漸變顏色,可以使用如下的canvas提供的幾個方法去簡便實現漸變效果:

addColorStop(offset, color) –addColorStop 方法接受 2 個參數,offset參數必須是一個 0.0 與 1.0 之間的數值,表示漸變中顏色所在的相對位置。例如,0.5 表示顏色會出現在正中間。color 參數必須是一個有效的 CSS 顏色值
createLinearGradient(x0, y0, x1, y1) –該方法接受 4 個參數,表示漸變的起點 (x1,y1) 與終點 (x2,y2)。
createRadialGradient(x0, y0, r0, x1, y1, r1) – 該方法接受 6 個參數,前三個定義一個以 (x1,y1) 為原點,半徑為 r1 的圓,后三個參數則定義另一個以 (x2,y2) 為原點,半徑為 r2 的圓。
下面的代碼演示了使用漸變的效果:
- var gradient = context.createLinearGradient(0, 0,0, 145);
- gradient.addColorStop(0, “#00ABEB”);
- gradient.addColorStop(0.5, “yellow”);
- gradient.addColorStop(0.8, “green”);
- gradient.addColorStop(1, “white”);
- context.fillStyle = gradient;
- context.fillRect(5, 5, 145, 145);
實現的效果如下圖:

原文:http://tech.it168.com/a2011/1108/1270/000001270295_all.shtml
【編輯推薦】