文章出處

前兩章我們掌握了線段、矩形和多邊形的繪制方法,今天我們主要是學習如何繪制圓弧和貝塞爾曲線。

圓弧的繪制

圓弧可以理解為一個圓上的某部分線段,在canvas中,繪制一條圓弧的語法如下:

ctx.arc( 圓心x坐標, 圓心y坐標, 圓的半徑r , 開始角度, 結束角度 );

其中的 “開始角度” 和 “結束角度” 是相對360度的順時針的極坐標而言的,可配合下圖理解:

我們來一個例子,繪制一個圓心坐標為(80,80),半徑為40,開始角度為30度,結束角度為90度,那么可以這樣繪制:

<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.arc( 80, 80, 40, 1/6*Math.PI, 1/2*Math.PI);
ctx.stroke();  //描邊
</script>

其中開始角和結束角我們分別設定為“1/6*Math.PI”和“1/2*Math.PI”,是因為canvas里的角度是以PI(π)為單位的,在js中寫作Math.PI,你可以把一個PI理解為180度,那么30度便是1/6個PI。上述代碼效果如下:

開始角和結束角也可以是負值,則角度從0度開始以逆時針方式獲取:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.arc( 80, 80, 40, -1/6*Math.PI, -1/2*Math.PI);
ctx.stroke();  //描邊

我們可以很輕松地來繪制一個完整的圓,將起始角設為0度,結束角設為360度(2*Math.PI)即可:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.arc( 80, 80, 40, 0, 2*Math.PI);

ctx.lineWidth = 3;  //描邊寬度為3px
ctx.strokeStyle = "yellow";
ctx.stroke();  //描邊
ctx.fillStyle = "#4DA6FF";
ctx.fill(); //填充顏色

注意給圓填充顏色我們使用的是 .fill() 方法,和多邊形的填充方式一樣。

接著說說 arc() 的好兄弟 arcTo() 方法,它可以在兩條線段之間連接起一條弧線,其語法如下

ctx.arcTo( 起點切線末端x坐標, 起點切線末端y坐標, 終點x坐標, 終點y坐標, 圓的半徑r );

可以配合下圖理解:

我們先不管什么“連接兩條線段”的事情,單純看下arcTo()繪制了怎樣的一條圓弧:

<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.moveTo(20,20);           // 創建開始點
ctx.arcTo(60,20,60,60,40); // 創建圓弧路徑
ctx.stroke();                
</script>

效果如下:

那么我們利用arcTo()方法來連接兩條直線吧:

<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.moveTo(20,20);
ctx.lineTo(60,20);
ctx.arcTo(100,20,100,60,40); // 創建圓弧路徑
ctx.lineTo(100,100);
ctx.stroke();                
</script>

效果如下:

需要知道的是 arc() 不會影響畫筆的位置,而 arcTo() 會把畫筆移到圓弧線的終點位置。

曲線的繪制

無論是arc()抑或arcTo(),均是繪制了一個正圓上的部分圓弧線段,下面講講更靈活的曲線的繪制。

首先介紹的是canvas中貝塞爾曲線的繪制。使用過AI等專業矢量制圖軟件的朋友相信能很好地理解這一部分。我們先看下在制圖軟件中用鋼筆工具繪制一條貝塞爾曲線的過程:

可以看到每兩點可以連成一條貝塞爾路徑,且每一個點都有一條方位控制線來控制曲線的彎曲程度和走向,在canvas中也是以類似形式控制貝塞爾曲線的形狀。

我們先來看看bezierCurveTo()的實現方式,它稱作“三次方貝塞爾曲線”,其語法為:

ctx.bezierCurveTo( CSx, CSy, CEx, CEy, Ex, Ey );

其中CSx、CSy表示貝塞爾曲線起點方向控制線末端的x坐標和y坐標。CEx、CEy表示貝塞爾曲線終點方向控制線末端的x坐標和y坐標。Ex、Ey表示貝塞爾曲線終點坐標。

參考圖如下,圖中的貝塞爾曲線起點坐標為(20,20),終點坐標為(200,20),起點的方向控制線末端坐標為(20,100),終點的方向控制線末端坐標為(200,100):

有的朋友可能會問為何bezierCurveTo()方法沒有起始點的參數,答案是起始點默認為bezierCurveTo()方法執行之前畫筆所在的位置,我們可以通過ctx.moveTo(x,y)來確定起始點的位置。

如上圖所示的貝塞爾曲線我們可以這樣繪制:

<canvas id="myCanvas" width="300" height="150" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.moveTo(20,20);   //確定起始點
ctx.bezierCurveTo( 20, 100, 200, 100, 200, 20 );
ctx.stroke();  //描邊
</script>

我們可以繪制兩條或者多條連在一起的貝塞爾曲線,從而塑造我們想要的曲線:

<canvas id="myCanvas" width="400" height="250" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.moveTo(20,120);   //確定起始點
ctx.bezierCurveTo( 20, 200, 200, 200, 200, 120 );   //繪制第一條貝塞爾曲線
ctx.bezierCurveTo( 200, 20, 380, 20, 380, 120 );  //繪制第二條貝塞爾曲線,該曲線起點為上一條曲線終點(200,120)
ctx.stroke();  //描邊
</script>

效果如下:

使用過矢量制圖軟件的朋友可能有個地方會困惑,那就是我們很多時候開始繪制一條曲線時(起點不做拉伸),該曲線的起點是沒有任何方向控制線的,如下圖:

如果我們要繪制一條起點不做方向控制的曲線,那么bezierCurveTo()方法就不再適用了。

針對這種情況,可以通過 quadraticCurveTo() 方法來解決,它稱作“二次方貝塞爾曲線”,語法為

ctx.quadraticCurveTo( CEx, CEy, Ex, Ey );

其中CEx、CEy表示曲線終點方向控制線末端的x坐標和y坐標。Ex、Ey表示曲線終點坐標。至于曲線起點則跟bezierCurveTo()一樣,為該方法執行前畫筆所在的位置。

我們試著來繪制一條這樣的曲線,它是我在AI中用鋼筆工具繪制出來的:

它的矢量輪廓是這樣的:

由于起點是沒有方向控制線的,我們很容易知道得先繪制一條quadraticCurve,然后再緊接著繪制一條bezierCurve來完成這條曲線。

我們先確定下各點的坐標:

然后輕松寫出代碼:

<canvas id="myCanvas" width="490" height="270" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象
ctx.moveTo(52,37);   //確定起始點
ctx.quadraticCurveTo( 45, 175, 172, 157 );   //繪制第一條曲線
ctx.bezierCurveTo( 298, 140, 337, 201, 312, 236 );  //繪制第二條曲線
ctx.stroke();  //描邊
</script>

效果如下,杠杠的:

本章暫時寫到這里,建議有興趣的朋友多實踐,其中貝塞爾曲線部分的知識點可以通過AI等矢量設計軟件來加深理解。共勉~

donate


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()