前兩章我們掌握了線段、矩形和多邊形的繪制方法,今天我們主要是學習如何繪制圓弧和貝塞爾曲線。
圓弧的繪制
圓弧可以理解為一個圓上的某部分線段,在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等矢量設計軟件來加深理解。共勉~
文章列表