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

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

如果不指定顏色,默認(rèn)的是使用黑色去填充整個矩形??梢允褂胒illStyle方法為矩形指定顏色或其他樣式,比如可以充分利用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中比傳統(tǒng)的rgb多了a,即透明度的含義,a的值也是0到1之間的數(shù)字,0表示完全透明,1則是完全不透明。運(yùn)行結(jié)果如下圖:

接下來學(xué)習(xí)如何繪制圓(弧),繪制用到的方法如下:
- arc(x, y, radius, startAngle, endAngle, anticlockwise)
畫圓或者圓弧。x,y為圓心坐標(biāo),radius為半徑,startAngle,endAngle為開始/結(jié)束劃圓的角度,anticlockwise為是否逆時針畫圓(True為逆時針,F(xiàn)alse為順時針)。
注意這里的角度為弧度制,所以如果畫一個正圓的話,是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();
結(jié)果如下圖:

接下來,我們學(xué)習(xí)如何畫貝塞爾曲線。HTML 5的API中,有一個畫這個曲線的很容易的方法bezierCurveTo,相關(guān)參數(shù)介紹如下:
bezierCurveTo (cp1x, cp1y, cp2x, cp2y, x, y):為一個畫布的當(dāng)前子路徑添加一條三次貝塞爾曲線。這條曲線的開始點(diǎn)是畫布的當(dāng)前點(diǎn),而結(jié)束點(diǎn)是 (x, y)。兩條貝塞爾曲線控制點(diǎn) (cpX1, cpY1) 和 (cpX2, cpY2) 定義了曲線的形狀。當(dāng)這個方法返回的時候,當(dāng)前的位置為 (x, y)。下面是相關(guān)代碼:
- 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();
顯示結(jié)果如下圖:

目前為止,我們使用的fillStyle都是使用一種單獨(dú)的顏色去填充圖形,而實際上,fillStyle也支持使用多種顏色去填充,比如下面的例子,隨機(jī)生成了各種顏色去填充畫布實現(xiàn)了彩虹的效果:
- 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;
- // 藍(lán)色
- 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提供的幾個方法去簡便實現(xiàn)漸變效果:

addColorStop(offset, color) –addColorStop 方法接受 2 個參數(shù),offset參數(shù)必須是一個 0.0 與 1.0 之間的數(shù)值,表示漸變中顏色所在的相對位置。例如,0.5 表示顏色會出現(xiàn)在正中間。color 參數(shù)必須是一個有效的 CSS 顏色值
createLinearGradient(x0, y0, x1, y1) –該方法接受 4 個參數(shù),表示漸變的起點(diǎn) (x1,y1) 與終點(diǎn) (x2,y2)。
createRadialGradient(x0, y0, r0, x1, y1, r1) – 該方法接受 6 個參數(shù),前三個定義一個以 (x1,y1) 為原點(diǎn),半徑為 r1 的圓,后三個參數(shù)則定義另一個以 (x2,y2) 為原點(diǎn),半徑為 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);
實現(xiàn)的效果如下圖:

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