原文:http://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes

在我們開始繪制圖形前,我們先探討一下canvas中的網(wǎng)格及坐標(biāo)空間。在前一篇教程中,我們定義了一個(gè)150*150的canvas區(qū)域,并在該區(qū)域繪制了一個(gè)圖形。在canvas區(qū)域中,以左上角為坐標(biāo)原點(diǎn)(0,0),坐標(biāo)最小單位為1px。區(qū)域內(nèi)所有元素相對(duì)與原點(diǎn)定位。不過(guò)在以后的實(shí)例中,我們還會(huì)向你展示如何重定義坐標(biāo)原點(diǎn)、旋轉(zhuǎn)坐標(biāo)甚至是重新定義坐標(biāo)單位,但是現(xiàn)在,我們還是從默認(rèn)設(shè)置開始學(xué)習(xí)。
與SVG語(yǔ)法不同的是,canvas只提供了一個(gè)繪制矩形的語(yǔ)法,其他形狀的繪制就必須依靠路徑功能來(lái)繪制了,哈哈,其實(shí)我們已經(jīng)收集了很多多繪制各種復(fù)雜多邊形的function,拿來(lái)就能用嘍。
Rectangles
首先讓我們來(lái)看下,目前有三種繪制矩形的語(yǔ)法:
fillRect(x,y,width,height) : 繪制一個(gè)實(shí)心的舉行strokeRect(x,y,width,height) : 繪制一個(gè)矩形邊框clearRect(x,y,width,height) : 繪制一個(gè)透明的矩形
以上三種方法中都有x和y參數(shù),這對(duì)參數(shù)的值就是相對(duì)于canvas原點(diǎn)(左上角)的距離。
以下代碼為之前教程中出現(xiàn)過(guò)的draw()函數(shù),我們這次將三種矩形繪制的方法都寫進(jìn)去:
function draw(){ var canvas = document.getElementById('tutorial'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); ctx.fillRect(25,25,100,100); ctx.clearRect(45,45,60,60); ctx.strokeRect(50,50,50,50); }}
繪制的效果見右圖,fillRect函數(shù)繪制了一個(gè)100*100的大矩形,clearRect函數(shù)從這個(gè)矩形挖掉了一塊60*60的矩形并且strokeRect函數(shù)又繪制了一個(gè)50*50的矩形邊框。在以后的教材中我們將看到另外的clearRect方法以及我們?nèi)绾螢榫匦翁畛洳煌念伾屠L制不同的邊框。
與接下來(lái)我們要講的path方法不同,以上三個(gè)矩形繪制方法執(zhí)行后都會(huì)立即應(yīng)用到canvas區(qū)域內(nèi)。
用路徑來(lái)繪制多邊形,以下這些方法我們都是需要的:
beginPath()closePath()stroke()fill()
第一步,我們使用beginPath方法聲明一個(gè)路徑,路徑的繪制需要用到一系列字方法(lines,arcs,ect)共同配合來(lái)完成一個(gè)多邊形,每次我們用到路徑來(lái)繪制多邊形時(shí),我們都需要聲明一個(gè)beginPath來(lái)開始繪制。
第二步,我們將需要調(diào)用一些特定方法來(lái)繪制我們需要的路徑,我們很快就會(huì)了解到。
第三步,closePath,是一個(gè)可選步驟,這個(gè)方法將封閉繪制路徑的起點(diǎn),如果該多邊形已經(jīng)被封閉,那么,這個(gè)方法將不產(chǎn)生任何作用。
最后的步驟,是運(yùn)用stroke或者fill方法,為繪制好的多邊形路徑填充顏色或者描邊。
注意:如果用fill方法填充一個(gè)未封閉的多邊形時(shí),該多邊形將被自動(dòng)封閉,無(wú)需closePath幫忙了。
例如,以下代碼將會(huì)繪制一個(gè)簡(jiǎn)單的三角形:
ctx.beginPath();ctx.moveTo(75,50);ctx.lineTo(100,75);ctx.lineTo(100,25);ctx.fill();
moveTo

這是一個(gè)非常有用的函數(shù),雖然該函數(shù)不會(huì)繪制任何東西,但是它是路徑描述中的一個(gè)重要的功能。
moveTo函數(shù)將傳入2個(gè)參數(shù),x坐標(biāo)和y坐標(biāo),以該坐標(biāo)點(diǎn)為一個(gè)新的繪制起點(diǎn)。
當(dāng)canvas初始化或者beginPath方法執(zhí)行后,最起始的坐標(biāo)點(diǎn)默認(rèn)是(0,0),在絕大多數(shù)的應(yīng)用中,我們會(huì)用moveTo方法來(lái)定位路徑繪制的起點(diǎn)。我們亦可以用此方法繪制一些沒(méi)有連接的路徑,比如右邊的這張笑臉圖,用紅色線條標(biāo)識(shí)出來(lái)的就是用moveTo方法來(lái)實(shí)現(xiàn)的。
示例:
ctx.beginPath();ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circlectx.moveTo(110,75);ctx.arc(75,75,35,0,Math.PI,false); // Mouth (clockwise)ctx.moveTo(65,65);ctx.arc(60,65,5,0,Math.PI*2,true); // Left eyectx.moveTo(95,65);ctx.arc(90,65,5,0,Math.PI*2,true); // Right eyectx.stroke();
Lines
顧名思義,畫直線的方法。
lineTo(x, y)

該方法帶的2個(gè)參數(shù)為線段終點(diǎn)的坐標(biāo),起點(diǎn)坐標(biāo)則依賴于上一個(gè)路徑所申明的終點(diǎn),當(dāng)然該線段的起點(diǎn)也可以是由moveTo方法所申明的坐標(biāo)。
示例:如右邊的圖片所示,我們繪制了2個(gè)三角形,一個(gè)做填充,一個(gè)做描邊。首先用beginPath方法申明一個(gè)新的路徑繪制,用moveTo方法定義繪制起點(diǎn)。
你可能會(huì)注意到繪制實(shí)心和空心的三角形,其語(yǔ)法略有差異,那是因?yàn)楫?dāng)一個(gè)多邊形需要填充時(shí),其會(huì)自動(dòng)封閉路徑的始末端。
// Filled trianglectx.beginPath();ctx.moveTo(25,25);ctx.lineTo(105,25);ctx.lineTo(25,105);ctx.fill();// Stroked trianglectx.beginPath();ctx.moveTo(125,125);ctx.lineTo(125,45);ctx.lineTo(45,125);ctx.closePath();ctx.stroke();
Arcs
該方法為繪制弧線或者圓形路徑時(shí)使用,該方法另一個(gè)寫法為arcTo,不過(guò)該寫法僅僅用于safari瀏覽器,而不會(huì)兼容采用Gecko為核心的瀏覽器。
arc(x, y, radius, startAngle, endAngle, anticlockwise)

該方法接收N個(gè)參數(shù):x和y為該段弧線所對(duì)應(yīng)的原點(diǎn)坐標(biāo);radius為半徑;startAngle和endAngle則決定了該段弧線的2個(gè)端點(diǎn),起始和結(jié)束的角度以坐標(biāo)系X軸為衡量基準(zhǔn);anticlockwise為一個(gè)布爾值參數(shù),當(dāng)為true時(shí)則逆時(shí)針?lè)较虍嫼粗畡t順時(shí)針。
警告:在firefox的某些beta版本中,最后一個(gè)參數(shù)被定義為clockwise,請(qǐng)確保將你的瀏覽器版本升級(jí)至最終發(fā)布版本。
注意:在本表達(dá)式中的Angle是以弧度為單位呈現(xiàn)的,實(shí)際運(yùn)用中,我們經(jīng)常需要在角度與弧度之間做一個(gè)轉(zhuǎn)換,其JS的轉(zhuǎn)換表達(dá)式為:var radians = (Math.PI/180)*degrees
示例:
for (i=0;i<4;i++){ for(j=0;j<3;j++){ ctx.beginPath(); var x = 25+j*50; // x coordinate var y = 25+i*50; // y coordinate var radius = 20; // Arc radius var startAngle = 0; // Starting point on circle var endAngle = Math.PI+(Math.PI*j)/2; // End point on circle var anticlockwise = i%2==0 ? false : true; // clockwise or anticlockwise ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); if (i>1){ ctx.fill(); } else { ctx.stroke(); } }}Bezier and quadratic curves
如果我們需繪制更加復(fù)雜的曲線路徑,我們或許該用到貝塞爾或者2次方程曲線。
quadraticCurveTo(cp1x, cp1y, x, y) // BROKEN in Firefox 1.5 (see work around below)bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

兩種曲線有何區(qū)別?我們可以參看一下右邊這張圖,2種曲線都有一個(gè)起點(diǎn)和終點(diǎn)(blue point),但是貝塞爾曲線僅有一個(gè)“control point”(red point),2次曲線則有2個(gè)。
兩個(gè)方法中的x和y參數(shù)都為曲線的終點(diǎn)坐標(biāo),cp1x和cp1y為第一control point的坐標(biāo),cp2x和cp2y為2次曲線的第二控制點(diǎn)。
熟練運(yùn)用2次曲線和貝塞爾曲線進(jìn)行路徑繪制,是一件蠻有挑戰(zhàn)性的工作,因?yàn)樗幌衲承┦噶坷L圖軟件,比如ADOBE Illustrator等具有直觀的視覺反饋,所以這使得我們?cè)诶L制一些復(fù)雜的曲線時(shí)會(huì)遇到一點(diǎn)小困難,不過(guò)如果你有耐心和時(shí)間的話,你肯定能繪制出許多復(fù)雜的曲線來(lái)。
二次曲線示例:

貝塞爾曲線示例:

新聞熱點(diǎn)
疑難解答
圖片精選