貝塞爾和二次方曲線Bezier and quadratic curves
接下來要介紹的路徑是貝塞爾曲線,它可以是二次和三次方的形式,一般用於繪製複雜而有規律的形狀。
quadraticCurveTo(cp1x, cp1y, x, y) // BROKEN in Firefox 1.5 (see work around below) bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
上面兩行程式碼的差異請見右圖。它們都有一個起點一個終點(圖中的藍點),但二次方貝塞爾曲線只有一個(紅色)控制點點)而三次方貝塞爾曲線有兩個。參數 x和y是終點座標,cp1x和cp1y 是第一個控制點的座標,cp2x和cp2y是第二個的。
使用二次方和三次方的貝塞爾曲線是相當有挑戰的,因為不像在向量繪圖軟體 Adobe Illustrator 裡那樣有即時的視覺回饋。因為用它來畫複雜圖形是比較麻煩的。但如果你有時間,並且最重要是有耐心,再複雜的圖形都可以畫出來的。下面我們來畫一個簡單 而又規律的圖形。這些例子都比較簡單。我們繪製的都是完整的圖形。
// Quadratric curves example ctx.beginPath(); ctx.moveTo(75,25); ctx.quadraticCurveTo(25,25,25,62.5); ctx.quadraticCurveTo(25,100,50,100); ctx.quadraticCurveTo(50,120,30,125); ctx.quadraticCurveTo(60,120,65,100); ctx.quadraticCurveTo(125,100,125,62.5); ctx.quadraticCurveTo(125,25,75,25); ctx.stroke();
透過計算,可以由二次曲線的單一控制點得出相應三次方曲線的兩個控制點,因此二次方轉三次方是可能的,但是反之不然。只有當三次方程式中的三次項為零是才可能轉換為二次的貝塞爾曲線。通常可以用多條二次方曲線透過細分演算法來近似模擬三次方貝塞爾曲線。
// Bezier curves example ctx.beginPath(); ctx.moveTo(75,40); ctx.bezierCurveTo(75,37,70,25,50,25); ctx.bezierCurveTo(20,25,20,62.5,20,62.5); ctx.bezierCurveTo(20,80,40,102,75,120); ctx.bezierCurveTo(110,102,130,80,130,62.5); ctx.bezierCurveTo(130,62.5,130,25,100,25); ctx.bezierCurveTo(85,25,75,37,75,40); ctx.fill();
矩形路徑 Rectangles
除了上面提到的三個方法可以直接繪製矩形之外,我們還有一個rect方法是用來繪製矩形路徑的。
rect(x, y, width, height)
它接受四個參數,x和y 是其左上角座標,width和height 是其寬和高。當它被調用時,moveTo方法會自動被調用,參數為(0,0),於是起始座標又恢復成初始原點了。
綜合樣本
在整個例子裡,最值得注意的是roundedRect函數的使用和fillStyle屬性的設定。自訂函數對於封裝複雜圖形的繪製是非常有用的。在這個例子裡使用自訂函數就省掉了大約一半的程式碼。在接下來的例子會深入探討fillStyle屬性的使用。這裡是用它來改變填充顏色,從預設的黑色,到白色,然後再回到黑色。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); roundedRect(ctx,12,12,150,150,15); roundedRect(ctx,19,19,150,150,9); roundedRect(ctx,53,53,49,33,10); roundedRect(ctx,53,119,49,16,6); roundedRect(ctx,135,53,49,33,10); roundedRect(ctx,135,119,25,49,10); ctx.beginPath(); ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false); //chiensexu 本来是true呵呵,反了 ctx.lineTo(31,37); ctx.fill(); for(i=0;i<8;i++){ ctx.fillRect(51+i*16,35,4,4); } for(i=0;i<6;i++){ ctx.fillRect(115,51+i*16,4,4); } for(i=0;i<8;i++){ ctx.fillRect(51+i*16,99,4,4); } ctx.beginPath(); ctx.moveTo(83,116); ctx.lineTo(83,102); ctx.bezierCurveTo(83,94,89,88,97,88); ctx.bezierCurveTo(105,88,111,94,111,102); ctx.lineTo(111,116); ctx.lineTo(106.333,111.333); ctx.lineTo(101.666,116); ctx.lineTo(97,111.333); ctx.lineTo(92.333,116); ctx.lineTo(87.666,111.333); ctx.lineTo(83,116); ctx.fill(); ctx.fillStyle = "white"; ctx.beginPath(); ctx.moveTo(91,96); ctx.bezierCurveTo(88,96,87,99,87,101); ctx.bezierCurveTo(87,103,88,106,91,106); ctx.bezierCurveTo(94,106,95,103,95,101); ctx.bezierCurveTo(95,99,94,96,91,96); ctx.moveTo(103,96); ctx.bezierCurveTo(100,96,99,99,99,101); ctx.bezierCurveTo(99,103,100,106,103,106); ctx.bezierCurveTo(106,106,107,103,107,101); ctx.bezierCurveTo(107,99,106,96,103,96); ctx.fill(); ctx.fillStyle = "black"; ctx.beginPath(); ctx.arc(101,102,2,0,Math.PI*2,true); ctx.fill(); ctx.beginPath(); ctx.arc(89,102,2,0,Math.PI*2,true); ctx.fill(); } function roundedRect(ctx,x,y,width,height,radius){ ctx.beginPath(); ctx.moveTo(x,y+radius); ctx.lineTo(x,y+height-radius); ctx.quadraticCurveTo(x,y+height,x+radius,y+height); ctx.lineTo(x+width-radius,y+height); ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius); ctx.lineTo(x+width,y+radius); ctx.quadraticCurveTo(x+width,y,x+width-radius,y); ctx.lineTo(x+radius,y); ctx.quadraticCurveTo(x,y,x,y+radius); ctx.stroke(); }
以上就是canvas遊戲開發學習之三:繪製複雜形狀的內容,更多相關內容請關注PHP中文網(m.sbmmt.com)!