HTML5 是一個新興標準,它正在以愈來愈快的速度替代久經考驗的 HTML4。HTML5 是一個 W3C 「工做草案」 — 意味着它仍然處於開發階段 — 它包含豐富的元素和屬性,它們都支持現行的 HTML 4.01 版本規範。它還引入了幾個新元素和屬性,它們適用許多使用 web 頁面的領域 — 音頻、視頻、圖形、數據存儲、內容呈現,等等。本文主要關注圖形方面的加強:canvas。javascript
新的 HTML5 canvas 是一個原生 HTML 繪圖簿,用於 JavaScript 代碼,不使用第三方工具。跨全部 web 瀏覽器的完整 HTML5 支持尚未完成,但在新興的支持中,canvas 已經能夠在幾乎全部現代瀏覽器上良好運行了,但 Windows® Internet Explorer® 除外。幸運的是,一個解決方案已經出現,將 Internet Explorer 也包含進來。php
本質上,canvas 元素是一個白板,直到您在它上面 「繪製」 一些可視內容。與擁有各類畫筆的藝術家不一樣,您使用不一樣的方法在 canvas 上做畫。您甚至能夠在 canvas 上建立並操做動畫,這不是使用畫筆和油彩所可以實現的。html
本文探索新的 HTML canvas 元素,從簡單地包含一個 canvas 元素到高級 JavaScript 交互(動畫的關鍵)逐步進行演示。學習如何在一個 web 頁面上顯示 canvas。本文針對 web 設計師和開發人員,儘管 JavaScript 知識不是必須的,但理解該語言的運行方式將有所幫助。可是,HTML 知識是關鍵所在,尤爲是如何建立一個基本 web 頁面。html5
要查看本文展現的示例的實時實例,您須要一個瀏覽器並能訪問 Internet。全部示例都在一個真實網站上提供(參見 參考資料)。java
肯定哪些瀏覽器支持 HTML5 和一個移動目標達到什麼程度。在本文撰寫之時,Google Chrome、Apple Safari 和 Mozilla Firefox 都支持大多數新的 HTML5 元素,它們都支持 canvas 元素。Internet Explorer 7 和 8 都不支持 HTML5;Internet Explorer 9 處於測試階段,支持 HTML5,但還有一些問題。web
在此期間,有一個針對不支持 HTML5 的 Internet Explorer 版本的補丁可用。這個補丁的前提是建立使用 JavaScript 代碼的元素。例如,可使用代碼段 document.createElement('canvas')
建立一個可識別的 Canvas 標記;可是,這並不意味着有東西通過元素自己 。一個流行的解決方法是包含一個完整的基於 canvas 的 JavaScript 庫,這個庫由 Google 提供,稱爲 ExplorerCanvas— 或簡稱 excanvas
。下載並將其做爲一個外部文件引用,以下所示。(參見 參考資料 中的連接,瞭解更多 excanvas
信息。)ajax
<!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]-->
經過包含 excanvas
,您向 Internet Explorer 提供 canvas 及其大多數方法。編程
因爲 canvas 只是一個 HTML 標記,所以它的顯示方式只是包含在標記中。第一個示例(如 圖 1 所示)顯示一個最簡單的 canvas。它之因此可見,是由於它經過 style
屬性得到了一個顏色方案,經過 width
和 height
屬性得到了其大小。canvas
這個頁面的代碼簡短明瞭,如 清單 1 所示。瀏覽器
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]--> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvasTag" width="400" height="400" style="border: 10px yellow solid"></canvas> <br /><br /> <a href="index.html">back</a> </div> </body> </html>
這個 canvas 的寬度和高度均爲 400 像素,邊框爲黃色,背景爲藍色。canvas 上沒有任何實際繪圖;繪圖經過屬於 canvas 的 JavaScript 方法完成。
表 1 列示了幾個附加到 canvas 上下文的方法。
方法 | 用途 |
---|---|
getContext(contextId) |
公開在 canvas 上繪圖須要的 API。唯一(當前)可用的 contextID 是 2d 。 |
height |
設置 canvas 的高度。默認值是 150 像素。 |
width |
設置 canvas 的寬度。默認值是 300 像素。 |
createLinearGradient(x1,y1,x2,y2) |
建立一個線性漸變。起始座標爲 x1,y1 ,結束座標爲 x2,y2 。 |
createRadialGradient(x1,y1,r1,x2,y2,r2) |
建立一個放射狀漸變。圓圈的起始座標是 x1,y1 ,半徑爲 r1 。圓圈的結束座標爲x2,y2 ,半徑爲 r2 。 |
addColorStop(offset, color) |
向一個漸變添加一個顏色中止。顏色中止(color stop) 是漸變中顏色更改發生的位置。offset 必須介於 0 到 1 之間。 |
fillStyle |
設置用於填充一個區域的顏色 — 例如,fillStyle='rgb(255,0,0)' . |
strokeStyle |
設置用於繪製一根直線的顏色 — 例如,fillStyle='rgb(255,0,0)' . |
fillRect(x,y,w,h) |
填充一個定位於 x 和 y ,寬度和高度分別爲 w 和 h 的矩形。 |
strokeRect(x,y,w,h) |
繪製一個定位於 x 和 y ,寬度和高度分別爲 w 和 h 的矩形的輪廓。 |
moveTo(x,y) |
將繪圖位置移動到座標 x,y 。 |
lineTo(x,y) |
從繪圖方法結束的最後位置到 |
scale(x,y)縮放
rotate(deg)旋轉角度
本小節將展現一系列示例,每一個示例的功能都比前一個示例略有增長。
首先,將一組矩形放置到 canvas 上。記住,矩形是擁有 4 條直邊和 4 個直角的圖形,正方形是矩形的變體。圖 2 顯示 canvas 上有一系列矩形,每一個矩形都比前一個略小。注意,每一個矩形的顏色都不一樣,使其更清晰明確。
清單 2 顯示了用於建立圖 2 中的 canvas 的代碼。每一個矩形都由兩行代碼建立:首先,fillStyle
方法使用顏色定義的紅、綠、藍(RGB)格式定義顏色(fillStyle='rgb(255,0,0)
)。而後,fillRect
方法(fillRect(50,50,300,300)
)定義大小。前兩個值設置起始座標,後兩個值設置結束座標。
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> <script> window.onload=function() { var mycanvas=document.getElementById("myCanvasTag"); var mycontext=mycanvas.getContext('2d'); mycontext.fillStyle='rgb(0,0,255)'; mycontext.fillRect(0,0,400,400); mycontext.fillStyle='rgb(255,0,0)'; mycontext.fillRect(50,50,300,300); mycontext.fillStyle='rgb(0,255,0)'; mycontext.fillRect(100,100,200,200); mycontext.fillStyle='rgb(100,100,100)'; mycontext.fillRect(125,175,150,25); } </script> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvasTag" width="400" height="400" style="border: 10px yellow solid"> </canvas> <br /><br /> <a href="index.html">back</a> </div> </body> </html>
要在 canvas 上繪圖,經過將 getContext('2d')
應用到 canvas 元素訪問提供方法的 API。經過這個 document.getElementById
方法,canvas 元素被設置爲一個 JavaScript 變量:
var mycanvas=document.getElementById("myCanvasTag");
而後將 getContext
應用到 canvas 元素,以下所示。
var mycontext=mycanvas.getContext('2d');
一旦一個變量被設置到上下文,全部方法就可使用了。
下一個示例展現如何結合兩種技術。一種是矩形重疊,方法是使用 fillRect
參數來定位矩形(見 圖 3)。
第二種技術是 RGB 顏色處理的變體,即添加透明度。不使用 rgb
,而是使用 rgba
。a
表示 alpha 通道,該通道控制透明度。在圖 3 中的示例中,第二個矩形的透明度被設置爲 50%(或 .5),第三個設置爲 25%(或 .25)。清單 3 顯示了完整的標記。
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> <script> window.onload=function() { var mycanvas=document.getElementById("myCanvasTag"); var mycontext=mycanvas.getContext('2d'); mycontext.fillStyle='rgb(0,0,255)'; mycontext.fillRect(30,30,300,300); mycontext.fillStyle='rgba(0,255,0,0.5)'; mycontext.fillRect(60,60,300,300); mycontext.fillStyle='rgba(255,0,0,0.25)'; mycontext.fillRect(90,90,300,300); } </script> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvasTag" width="400" height="400" style="border: 10px yellow solid"> </canvas> <br /><br /> <a href="index.html">back</a> </div> </body> </html>
漸變— 通過協調的顏色混合 — 原生於 canvas ,經過兩種方法:createLinearGradient
和 createRadialGradient
。圖 4 展現了一個線性漸變。addColorStop
方法定義一個顏色,以及它在漸變中變爲活動狀態的位置。因爲一個漸變能夠擁有多個顏色中止,所以這種定位是主觀的。顏色定位值必須介於 0 到 1 之間,但測試變體和顏色中止的數量能夠生成不一樣的結果,即便一個值(好比 .25)保持不變。換句話說,一個顏色中止能夠將其位置設定爲 .25,可是相關顏色能夠從整個漸變路徑的四分之一處以後一點開始發生,一直持續到漸變結束,具體狀況取決於您設置其餘顏色中止的位置。記住,這是一個新的實現,可能還在改進過程當中。漸變的一個好處是它們老是引人注目,不管代碼和結果是否通過完美的協調。
圖 4 中的漸變經過 清單 4 中的 JavaScript 代碼建立。
var mycanvas=document.getElementById("myCanvasTag"); var mycontext=mycanvas.getContext('2d'); var mygradient=mycontext.createLinearGradient(30,30,300,300); mygradient.addColorStop(0,"#FF0000"); mygradient.addColorStop(1,"#00FF00"); mycontext.fillStyle=mygradient; mycontext.fillRect(0,0,400,400);
注意,清單 4 中的顏色中止被全面實現爲從這個方法自己建立的一個實時(on-the-fly)漸變的一個方法。語句mygradient.addColorStop(0,"#FF0000")
顯示顏色中止擁有兩個參數:位置和顏色。
圖 5 展現了一個放射狀漸變。用於建立這個漸變的代碼與清單 4 中的代碼相似,除了使用 createRadialGradient
方法替代createLinearGradient
方法以外。
用於建立圖 5 中的放射狀漸變的代碼如 清單 5 所示。注意全部 5 個顏色中止。
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> <script> window.onload=function() { var mycanvas=document.getElementById("myCanvasTag"); var mycontext=mycanvas.getContext('2d'); var mygradient=mycontext.createRadialGradient(300,300,0,300,300,300); mygradient.addColorStop("0","magenta"); mygradient.addColorStop(".25","blue"); mygradient.addColorStop(".50","green"); mygradient.addColorStop(".75","yellow"); mygradient.addColorStop("1.0","red"); mycontext.fillStyle=mygradient; mycontext.fillRect(0,0,400,400); } </script> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvasTag" width="400" height="400" style="border: 10px blue solid"> </canvas> <br /><br /> <a href="index.html">back</a> </div> </body> </html>
一個 web 頁面可以包含多個 canvas,每一個 canvas 引用它們本身的獨特 JavaScript 上下文變量。結果,每一個 canvas 都獨立於其餘 canvas 工做。圖 6 展現了 4 個 canvas,每一個 canvas 上的圖像都不一樣。
清單 6 顯示了用於建立圖 6 中的頁面的代碼。注意,每一個 canvas 都有一個唯一 ID 且每一個上下文都是唯一的。
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> <script> window.onload=function() { var mycontext1=document.getElementById("myCanvasTag1").getContext('2d'); var mycontext2=document.getElementById("myCanvasTag2").getContext('2d'); var mycontext3=document.getElementById("myCanvasTag3").getContext('2d'); var mycontext4=document.getElementById("myCanvasTag4").getContext('2d'); // gradient 1 var mygradient1=mycontext1.createLinearGradient(30,30,90,90); mygradient1.addColorStop(0,"#FF0000"); mygradient1.addColorStop(1,"#00FF00"); mycontext1.fillStyle=mygradient1; mycontext1.fillRect(0,0,100,100); // gradient 2 var mygradient2=mycontext2.createLinearGradient(30,30,90,90); mygradient2.addColorStop(1,"#FF0000"); mygradient2.addColorStop(0,"#00FF00"); mycontext2.fillStyle=mygradient2; mycontext2.fillRect(0,0,100,100); var mygradient3=mycontext3.createLinearGradient(30,30,90,90); mygradient3.addColorStop(0,"#0000FF"); mygradient3.addColorStop(.5,"#00FFDD"); mycontext3.fillStyle=mygradient3; mycontext3.fillRect(0,0,100,100); var mygradient4=mycontext1.createLinearGradient(30,30,90,90); mygradient4.addColorStop(0,"#DD33CC"); mygradient4.addColorStop(1,"#EEEEEE"); mycontext4.fillStyle=mygradient4; mycontext4.fillRect(0,0,100,100); } </script> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvasTag1" width="100" height="100" style="border: 10px blue solid"> </canvas> <canvas id="myCanvasTag2" width="100" height="100" style="border: 10px green solid"> </canvas> <br /> <canvas id="myCanvasTag3" width="100" height="100" style="border: 10px red solid"> </canvas> <canvas id="myCanvasTag4" width="100" height="100" style="border: 10px black solid"> </canvas> <br /><br /> <a href="index.html">back</a> </div> </body> </html>
本文已經展現了可用於 canvas 的各類方法,每種方法都建立了一個可視結果。如今咱們提升一個等級,看看 canvas 如何實現事件和動畫。JavaScript 可以識別許多事件,包括在一個特定 web 頁面元素上方移動或懸停鼠標。JavaScript 語言可以識別更多事件,下面的示例將使用其中幾個。
圖 7 中的示例是使用前面清單中的方法建立的。如今咱們添加幾個新技術。面部的鼻子、眼睛和圓形項目以及外部邊界都使用 arc
方法建立。眼睫毛被繪製爲線條,嘴被建立爲一條貝賽爾曲線。圖 7 還在 canvas 底部顯示了一些文本,這是使用 fillText
方法建立的。
清單 7 顯示圖 7 使用的代碼。
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> <script> window.onload=function() { var mycanvas=document.getElementById("myCanvasTag"); var mycontext=mycanvas.getContext('2d'); //draw face mycontext.beginPath(); mycontext.arc(300, 250, 200, 0, Math.PI * 2, true); mycontext.closePath(); mycontext.stroke(); //draw left eye mycontext.beginPath(); mycontext.arc(220, 150, 30, 0, Math.PI * 2, true); mycontext.closePath(); mycontext.fillStyle='rgb(100,100,225)'; mycontext.fill(); //draw left iris mycontext.beginPath(); mycontext.arc(220, 150, 10, 0, Math.PI * 2, true); mycontext.closePath(); mycontext.fillStyle='rgb(0,0,0)'; mycontext.fill(); //draw left eyelid mycontext.beginPath(); mycontext.arc(220, 150, 30, 0, Math.PI, true); mycontext.closePath(); mycontext.fillStyle='rgb(200,200,200)'; mycontext.fill(); //draw left eyelashes mycontext.strokeStyle='rgb(0,0,0)'; lashes(mycontext,198, 170, 193, 185); lashes(mycontext,208, 177, 204, 193); lashes(mycontext,220, 180, 220, 195); lashes(mycontext,232, 177, 236, 193); lashes(mycontext,242, 170, 247, 185); mycontext.stroke(); openeye(); //draw right eyelashes mycontext.strokeStyle='rgb(0,0,0)'; lashes(mycontext, 358, 170, 353, 185); lashes(mycontext, 368, 177, 364, 193); lashes(mycontext, 380, 180, 380, 195); lashes(mycontext, 392, 177, 396, 193); lashes(mycontext, 402, 170, 407, 185); mycontext.stroke(); //draw nose mycontext.beginPath(); mycontext.arc(300, 250, 20, 0, Math.PI * 2, true); mycontext.closePath(); mycontext.stroke(); // draw smile mycontext.beginPath(); mycontext.lineWidth = 10; mycontext.moveTo(180, 320); mycontext.bezierCurveTo(140, 320, 340, 420, 400, 360); mycontext.closePath(); mycontext.stroke(); //draw message at bottom mycontext.font="1em sans-serif"; mycontext.fillStyle="rgb(0,0,0)"; mycontext.fillText("Move the mouse over and off the canvas - the face winks!", 10, 480); } function lashes(cntx,x1,y1,x2,y2) { cntx.moveTo(x1,y1); cntx.lineTo(x2,y2); } function closeeye() { //close right eye var mycanvas=document.getElementById("myCanvasTag"); var mycontext=mycanvas.getContext('2d'); mycontext.beginPath(); mycontext.arc(380, 150, 30, 0, Math.PI * 2, true); mycontext.closePath(); mycontext.fillStyle='rgb(200,200,200)'; mycontext.fill(); } function openeye() { //open right eye var mycanvas=document.getElementById("myCanvasTag"); var mycontext=mycanvas.getContext('2d'); mycontext.beginPath(); mycontext.arc(380, 150, 30, 0, Math.PI * 2, true); mycontext.closePath(); mycontext.fillStyle='rgb(100,100,225)'; mycontext.fill(); //draw right iris mycontext.beginPath(); mycontext.arc(380, 150, 10, 0, Math.PI * 2, true); mycontext.closePath(); mycontext.fillStyle='rgb(0,0,0)'; mycontext.fill(); //draw right eyelid mycontext.beginPath(); mycontext.arc(380, 150, 30, 0, Math.PI, true); mycontext.closePath(); mycontext.fillStyle='rgb(200,200,200)'; mycontext.fill(); } </script> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvasTag" width="600" height="500" style="border: 5px blue solid" onmouseover="closeeye()" onmouseout="openeye()"></canvas> <br /><br /> <a href="index.html">back</a> </div> </body> </html>
圖 7 中的臉經過一些 JavaScript 事件而改變。特別是, onmouseover
和 onmouseout
事件分別用於調用 closeeye()
和 openeye()
函數。這些函數不是 canvas 的方法,可是標準 JavaScript 函數。事件和函數之間的鏈接在 canvas 元素自己中進行。在 清單 7 中,頁面的主體區域接近代碼的底部,那是 canvas 所在的位置。canvas 標記內是:
onmouseover="closeeye()" onmouseout="openeye()"
清單 7 中出現了一個新的構造 —beginPath()
和 endPath()
的使用,它們用於明確區分獨立的複雜繪圖動做。封裝在其中的代碼繪製一個特殊的圖像,以分隔其餘繪圖動做。
關於 清單 7 中的代碼的幾個值得注意的地方列示以下:
openeye()
函數來繪製右眼。fillText
方法將文本寫到 canvas 上。arc
方法中,MATH.PI * 2
建立了一個完整的圓圈,而 MATH.PI
將只建立一個半圓(例如,眼皮)。JavaScript 打包了一個強大的編程利器。這種語言可以執行不少操控,如 清單 8 所示。這個代碼重複運行,在 canvas 上繪製一些線條。線條顏色隨機設置。
<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvasTag" width="400" height="400" style="border: 10px blue solid"> </canvas> <br /><br /> <a href="index.html">back</a> </div> <script> var mycanvas = document.getElementById("myCanvasTag") var mycontext = mycanvas.getContext('2d'); var x; var y; var x2; var y2; var r; var g; var b; function line() { x=Math.floor(Math.random()*190) + Math.floor(Math.random()*190); y=Math.floor(Math.random()*190) + Math.floor(Math.random()*190); x2=Math.floor(Math.random()*190) + Math.floor(Math.random()*190); y2=Math.floor(Math.random()*190) + Math.floor(Math.random()*190); r=Math.floor(Math.random()*255); g=Math.floor(Math.random()*255); b=Math.floor(Math.random()*255); mycontext.moveTo(x, y); mycontext.lineTo(x2, y2); mycontext.strokeStyle='rgb(' + r + ',' + g + ',' + b + ')'; mycontext.lineWidth=Math.floor(Math.random()*6); mycontext.stroke(); mycontext.restore(); } setInterval(line, 100); </script> </body> </html>
圖 8 顯示了這個動畫的一張快照。清單 8 中的代碼與本文其餘全部代碼示例都不一樣,由於 JavaScript 塊被放置到頁面底部,canvas 元素下方。這確保 canvas 在代碼運行以前就已經被呈現了。
HTML5 被定位於用於改變 web 開發的面貌。新的元素使得頁面佈局更簡單,支持經過瀏覽器存儲本地數據,擁有 canvas 之類的音頻、視頻和圖形平臺。隨着瀏覽器升級以支持更多新功能,web 的性質和用戶體驗將變得妙不可言。web 開發前景一片光明!
文章出處:http://www.ibm.com/developerworks/cn/web/wa-html5canvas/#ibm-pcon