
一條HTML5 canvas路徑是通過(guò)繪制指令來(lái)連接一系列的點(diǎn),由這一系列的點(diǎn)構(gòu)成直線或曲線。路徑可以用于在HTML5 canvas上繪制各種類(lèi)型的圖形:直線、圓形、多邊形等等。路徑的繪制是canvas的核心,必須很好的理解和掌握。
開(kāi)始和關(guān)閉一條路徑
要開(kāi)始和關(guān)閉一條路徑可以使用2D上下文的beginPath()和closePath()函數(shù)。例如下面的例子:
- var canvas = document.getElementById("ex1");
- var context = canvas.getContext("2d");
-
- context.beginPath();
-
- //... 繪制路徑
-
- context.closePath();
moveTo()函數(shù)
當(dāng)你在canvas中繪制一條路徑的時(shí)候,你可以想象自己正在使用一支“虛擬筆”。這支虛擬筆總是位于某個(gè)位置,你可以使用2D上下文的moveTo(x, y)函數(shù)來(lái)移動(dòng)這支虛擬筆。例如下面的代碼:
- context.moveTo(10,10);
這個(gè)例子將“虛擬筆”移動(dòng)到(10,10)這個(gè)坐標(biāo)點(diǎn)上。
lineTo()函數(shù)
lineTo函數(shù)用于從虛擬筆的當(dāng)前位置繪制一條直線到lineTo()函數(shù)中指定的點(diǎn)。下面是一個(gè)例子:
- context.beginPath();
-
- context.moveTo(10,10);
- context.lineTo(50,50);
-
- context.closePath();
這個(gè)例子中首先移動(dòng)虛擬筆到(10,10)坐標(biāo)點(diǎn)位置,然后從這個(gè)點(diǎn)繪制一條直線到(50,50)坐標(biāo)點(diǎn)。
lineTo()函數(shù)還會(huì)將虛擬筆移動(dòng)到執(zhí)行的結(jié)束點(diǎn)位置。上面的例子中是移動(dòng)到(50,50)的位置。
stroke()函數(shù) + fill()函數(shù)
在你沒(méi)有通知2D上下文繪制路徑之前,實(shí)際是不會(huì)在畫(huà)布上繪制任何東西的。你可以通過(guò)stroke()或fill()函數(shù)來(lái)通知2D上下文。
stroke()函數(shù)用于路徑操作指定的圖形的外輪廓。
fill()函數(shù)用于填充有路徑操作指定的圖形。
下面的例子展示了stroke()或fill()函數(shù)的用法。
- context.beginPath();
- context.moveTo(10,10);
- context.lineTo(60,50);
- context.lineTo(110,50);
- context.lineTo(10,10);
- context.stroke();
- context.closePath();
-
- context.beginPath();
- context.moveTo(100,10);
- context.lineTo(150,50);
- context.lineTo(200,50);
- context.lineTo(100,10);
- context.fill();
- context.closePath();
上面代碼的返回結(jié)果如下:

線條的寬度
你可以使用2D上下文的lineWidth屬性來(lái)設(shè)置繪制線條的寬度。下面是一個(gè)例子:
- context.lineWidth = 10;
上面的例子設(shè)置繪制線條的寬度為10像素。
下面的例子繪制3條直線,它們的寬度分別為1,5和10。

當(dāng)你繪制的線條寬度大于1的時(shí)候,擴(kuò)展的線條寬度將平均分配在線條中心線的兩側(cè)。距離來(lái)說(shuō),如果你從(10,10)這個(gè)點(diǎn)繪制一條直線到(100,10)這個(gè)點(diǎn),線條的寬度為10,那么,實(shí)際上是從(10,5)這個(gè)點(diǎn)開(kāi)始繪制,然后擴(kuò)展到(10,15)這個(gè)點(diǎn),在水平繪制到(100,5)和(100,15)這兩個(gè)點(diǎn),就像是繪制一個(gè)矩形。
線條的線條(LINE CAP)
在使用路徑來(lái)繪制線條的時(shí)候,你可以設(shè)置線條的線頭樣式。線頭的樣式通過(guò)2D上下文的lineCap屬性來(lái)設(shè)置。它有三個(gè)可選值:
- butt
- round
- square
butt樣式的線頭是扁平且和線正交的樣式。
round樣式的線頭是一個(gè)圓角的線頭,圓的半徑等于線條寬度的一半。
square樣式的線頭會(huì)在線的末端繪制一個(gè)矩形。矩形的大小為:線條的寬度 X 線條的寬/2。
下面是幾個(gè)不同線頭樣式的線條的例子。所有的線條的寬度都是10。最總版的一組線條的lineCap的取值為butt,中間的一組線條的lineCap的取值為round,最右邊的一組線條的lineCap的取值為square。

lineCap的取值butt和square非常相似。有時(shí)難以區(qū)別。這里制作了幾個(gè)小例子,從這些例子中你可以看出它們之間的微小差別。下面又三組線條,每一組左邊(或上邊)的線條的lineCap屬性取值為butt,右邊(或下邊)的線條的lineCap屬性取值為square。

正如上面的結(jié)果所示,square線頭的線條要比butt線頭的線條要長(zhǎng)。
線條的連接
2D上下文的lineJoin屬性用于定義兩條線條連接處的點(diǎn)如何繪制。兩條線條連接處的點(diǎn)被稱(chēng)為“連接點(diǎn)”。lineJoin屬性有下面的三種取值:
- miter
- bevel
- round
下面是這三種取值的示例代碼:
- context.lineJoin = "miter";
- context.lineJoin = "bevel";
- context.lineJoin = "round";
miter的連接點(diǎn)是一個(gè)三角形的連接點(diǎn)。
bevel的連接點(diǎn)是一個(gè)平頭的連接點(diǎn)。
round的連接點(diǎn)是一個(gè)圓角的連接點(diǎn)。
下面分別是三種線條連接點(diǎn)的例子,從左到右的lineJoin屬性分別是:miter,bevel和round。

繪制曲線
2D上下文的arc()函數(shù)可以用于繪制一條曲線。arc()函數(shù)有6個(gè)參數(shù):
- x:圓弧的中心點(diǎn)的X坐標(biāo)位置。
- y:圓弧的中心點(diǎn)的Y坐標(biāo)位置。
- radius:圓弧的半徑。
- startAngle:圓弧開(kāi)始的角弧度。
- endAngle:圓弧結(jié)束的角弧度。
- anticlockwise:設(shè)置是以順時(shí)針還是逆時(shí)針繪制圓弧,false為順時(shí)針。
下面是一段示例代碼:
- context.lineWidth = 3;
-
- var x = 50;
- var y = 50;
- var radius = 25;
- var startAngle = (Math.PI / 180) * 45;
- var endAngle = (Math.PI / 180) * 180;
- var anticlockwise = false;
-
- context.beginPath();
- context.arc(x, y, radius, startAngle, endAngle, anticlockwise);
- context.stroke();
- context.closePath();
上面的代碼繪制了一條弧線,它的中心點(diǎn)位于(50,50)坐標(biāo)點(diǎn),半徑為25,從45度開(kāi)始到180度結(jié)束。
下面是上面代碼的返回結(jié)果:

上面的例子如果將anticlockwise設(shè)置為true,會(huì)得到下面的結(jié)果:

如果你要花一個(gè)完整的圓,可以簡(jiǎn)單的設(shè)置startAngle為0,endAngle設(shè)置為2 * Math.PI,它相當(dāng)于(Math.PI / 180) * 360。
arcTo()函數(shù)
2D上下文中有一個(gè)arcTo()函數(shù),它用于從當(dāng)前的點(diǎn)繪制一條曲線到參數(shù)指定的點(diǎn),曲線的半徑也由參數(shù)指定。它的語(yǔ)法為:arcTo(x1, y1, x2, y2, radius)。注意:參數(shù)中x1, y1, x2, y2指的是這個(gè)點(diǎn)的控制點(diǎn)。arcTo()函數(shù)可以使用lineTo()和arc函數(shù)來(lái)模仿。
quadraticCurveTo()函數(shù)
quadraticCurveTo()函數(shù)用于繪制一條二次貝茲曲線。這條曲線由一個(gè)控制點(diǎn)來(lái)控制,它的語(yǔ)法為:quadraticCurveTo(cp1x, cp1y, x, y)。下面是一個(gè)示例代碼:
- context.lineWidth = 3;
-
- var fromX = 50;
- var fromY = 50;
- var toX = 100;
- var toY = 50;
- var cpX = 75;
- var cpY = 100;
-
- context.beginPath();
- context.moveTo(fromX, fromY);
- context.quadraticCurveTo(cpX, cpY, toX, toY);
- context.stroke();
- context.closePath();
上面的代碼繪制一條從(50,50)開(kāi)始到(100,50)的二次貝茲曲線,這條曲線的控制點(diǎn)為(75,100)。得到的結(jié)果如下所示:

仔細(xì)看,在曲線下方有一個(gè)小點(diǎn),那是這條曲線的控制點(diǎn)。(這個(gè)點(diǎn)是專(zhuān)門(mén)繪制出來(lái)讓大家看的)
關(guān)于控制點(diǎn),可以參考下面的圖像:

bezierCurveTo()函數(shù)
bezierCurveTo()函數(shù)用于從一個(gè)點(diǎn)到另一個(gè)點(diǎn)繪制一條三次貝茲曲線。三次貝茲曲線有兩個(gè)控制點(diǎn),而二次貝茲曲線只有一個(gè)控制點(diǎn)。它的語(yǔ)法為:bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)。下面是一個(gè)例子:
- context.lineWidth = 3;
-
- var fromX = 50;
- var fromY = 50;
- var toX = 300;
- var toY = 50;
- var cp1X = 100;
- var cp1Y = 100;
- var cp2X = 250;
- var cp2Y = 100;
-
- context.beginPath();
- context.moveTo(fromX, fromY);
- context.bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, toX, toY);
- context.stroke();
- context.closePath();
這段代碼從(50,50)繪制一條三次貝茲曲線到(300,50),兩個(gè)控制點(diǎn)分別為:(100,100)和(250,100)。得到的結(jié)果如下:

曲線下方的兩個(gè)小圓點(diǎn)是兩個(gè)控制點(diǎn),他們并不是曲線的一部分。
下面是一個(gè)不同的例子,它的開(kāi)始點(diǎn)和結(jié)束點(diǎn)于上面的例子相同,但是控制點(diǎn)和上面的例子不相同。
- context.lineWidth = 3;
-
- var fromX = 50;
- var fromY = 50;
- var toX = 300;
- var toY = 50;
- var cp1X = 100;
- var cp1Y = 10;
- var cp2X = 250;
- var cp2Y = 100;
-
- context.beginPath();
- context.moveTo(fromX, fromY);
- context.bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, toX, toY);
- context.stroke();
- context.closePath();
上面的代碼得到的結(jié)果如下:

文章的最后,我們引用MDN上的一個(gè)例子,它用Canvas路徑繪制出“吃豆人”游戲的一個(gè)小場(chǎng)景:

實(shí)現(xiàn)的代碼如下:
- function draw() {
- var canvas = document.getElementById('canvas');
- if (canvas.getContext){
- var ctx = 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);
- ctx.lineTo(31,37);
- ctx.fill();
-
- for(var 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();
- }
- }
-
- // A utility function to draw a rectangle with rounded corners.
-
- 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();
- }
本文版權(quán)屬于jQuery之家,轉(zhuǎn)載請(qǐng)注明出處:http://www.htmleaf.com/ziliaoku/ ... g/201507122217.html
【網(wǎng)站聲明】本站除付費(fèi)源碼經(jīng)過(guò)測(cè)試外,其他素材未做測(cè)試,不保證完整性,網(wǎng)站上部分源碼僅限學(xué)習(xí)交流,請(qǐng)勿用于商業(yè)用途。如損害你的權(quán)益請(qǐng)聯(lián)系客服QQ:2655101040 給予處理,謝謝支持。