Canvas繪圖環境中有些屬於立即繪製圖形方法,有些繪圖方法是基於路徑的。
立即繪製圖形方法只有兩個strokeRect(),fillRect(),雖然strokezText(),fillText()方法也是立即繪製的,但是文字不算是圖形。
基於路徑的繪製系統大多數繪製系統,如:SVG(Scalable Verctor Graphics, 可縮放的向量圖形),Adobe Illustrator等,都是基於路徑的,
使用這些繪製系統時,你需要先定義一個路徑,然後再對其進行描邊或填充,也可以描邊加填充這樣圖形才能顯示出來。
Canvas中的三種繪製方式:
繪製一條線段Canvas繪圖環境中,線段也是基於路徑繪製的,稱為線性路徑,創建線性路徑的方法:moveTO()與lineTo(),在創建路徑之後調用stroke()方法,才能在Canvas中畫出線段出來。
這就是前面我們所說的基於路徑的繪製方法,必須對其進行描邊或填充;
通常兩點連一線因此繪製線段非常簡單,透過moveTO()指定線的起點,透過lineTo()移動到另一個點。
function drawLine(){ cxt.moveTo(50, 50); cxt.lineTo(100, 100);}然而這樣我們在畫布中是看不見線段的,前面我們說到基於路徑的繪製方法,必須描邊或填滿。所以要看到結果,我們必須還要使用stroke()方法。
因此我們把方法修改成下面這樣就會畫出一條線段
function drawLine(){ cxt.moveTo(50, 50); cxt.lineTo(200, 200); cxt.stroke();}我們只使用lineTo()也是能在畫布中繪製出線段的,我們把上面的程式碼改成如下面所示,效果也是一樣的
function drawLine(){ cxt.lineTo(50, 50); cxt.lineTo(200, 200); cxt.stroke();}總結下moveTo()與lineTo()的用法
改變線段的寬度
function= 14; cxt.lineTo(50, 50); cxt.lineTo(200, 200); cxt.stroke();}改變線段的顏色
function drawLine(){ cxt.lineWidth = 14; cxt.strokeStyle = 'green'; cxt.lineTo(50, 50); cxt.lineTo(200, 200); cxt.stroke();}我們也可以利用CanvasGradient物件或CanvasPattern物件為線段添加漸層色或圖案
function drawLine(){ cxt.lineWidth = 14; var gradient = cxt.createLinearGradient(0, 0, canvas.width/2, canvas.height/2); gradient.addColorStop(0, 'blue'); gradient.addorStop(ColorStop(); 0.5, 'purple'); gradient.addColorStop(1, 'yellow'); cxt.strokeStyle = gradient; cxt.lineTo(50, 50); cxt.lineTo(200, 200); cxt.stroke();} beginPath()與closePath()從上面canvas中的三種繪製方式中我們可以看出,第二行的弧形路徑是開放路徑,最後一行的弧形是封閉路徑。那麼封閉的路徑是怎麼實現的呢?
下面我們來看看canvas中路徑繪製中兩個比較重要的方法
先繪製出一條折線
function drawLine(){ cxt.strokeStyle = 'green'; cxt.lineWidth = 2; cxt.moveTo(50, 50); cxt.lineTo(50, 150); cxt.lineTo(150, 150); cxt.stroke(lineTo(150, 150); cxt.stroke( );}修改上面範例中的程式碼在程式碼中加入beginPath()與closePath()方法
function drawLine(){ //描邊三角形cxt.strokeStyle = 'green'; cxt.lineWidth = 2; cxt.beginPath(); cxt.moveTo(50, 50); cxt.lineTo(50, 150); cxt. stroke(); cxt.beginPath(); cxt.lineTo(150, 150); cxt.lineTo(150, 250); cxt.stroke(); cxt.closePath();}可以看出我們在畫布中繪製了兩條路徑
注意:在呼叫beginPath()之後,或在canvas剛建的時候,第一條路徑構造指令通常被視為moveTo()。所以我們在繪製圖形的時候一定要先使用beginPath()。
我們繼續修改我們的程式碼
function drawLine(){ //描邊三角形cxt.strokeStyle = 'green'; cxt.lineWidth = 2; cxt.beginPath(); cxt.moveTo(50, 50); cxt.lineTo(50, 150); cxt. lineTo(150, 150); cxt.closePath(); cxt.stroke(); //折線cxt.translate(150, 0); cxt.strokeStyle = 'red'; cxt.lineWidth = 2; cxt.beginPath(); cxt.moveTo(50, 50); cxt.lineTo (50, 150); cxt.lineTo(150, 150); cxt.stroke(); cxt.closePath(); //綠色填滿三角形cxt.translate(150, 0); cxt.fillStyle = 'green'; cxt.lineWidth = 2; cxt.beginPath(); cxt.moveTo( 50, 50); cxt.lineTo(50, 150); cxt.lineTo(150, 150); cxt.fill(); cxt.closePath(); //紅色填滿三角形cxt.translate(150, 0); cxt.fillStyle = 'red'; cxt.lineWidth = 2; cxt.beginPath(); cxt .moveTo(50, 50); cxt.lineTo(50, 150); cxt.lineTo(150, 150); cxt.closePath(); cxt.fill();}從上面的例子我們可以看出closePath()的位置不同,也會影響我們的圖形
注意:當你呼叫fill()函數時,所有沒有閉合的形狀都會自動閉合,所以此時closePath()函數不是必須的。
但呼叫stroke():如果你在stroke()方法之前只用closePath()會形成閉合路徑,如果在stroke()方法之後呼叫closePath()方法,此時圖形已經繪製完成,目前的繪製路徑已經關閉,所以closePath()方法不起作用。
線段與像素邊界先來看一個例子
function drawLine(){ //描邊三角形cxt.lineWidth = 1; cxt.beginPath(); cxt.moveTo(50, 50); cxt.lineTo(450, 50); cxt.stroke(); cxt.beginPath( ); cxt.moveTo(50.5, 150.5); cxt.lineTo(450.5, 150.5); cxt.stroke();}從圖中我們可以看出,我們將兩條線段的lineWidth都是設定為1像素,但上面的線段畫出的卻是兩像素。
如果你在某2個像素的邊界處繪製一條1像素寬的線段,那麼該線段實際上會佔據2個像素的寬度;
因為當你在像素邊界處繪製一條1像素寬度的垂直線段時,canvas的繪圖環境物件會試著將半個像素畫在邊界中線的右邊,將另外半個像素畫在邊界中線的左邊。
然而,在一個整像素的範圍內繪製半個像素寬的線段是不可能的,所以在左右兩個方向上的半個像素都被擴展為1個像素。
另外一方面,繪製在兩個像素之間,這樣的話,中線左右兩端的那半個像素就不會延伸,它們結合起來恰好佔據1個像素的寬度。所以說,如果要繪製一條真正1像素寬度的線段,你必須將該線段繪製在某兩個像素之間
網格的繪製既然我們已經明白如何繪製真正的1像素的線段,那我們就開始繪製網格
function drawLine(stepx, stepy){ cxt.lineWidth = 0.5; cxt.strokeStyle = 'green'; //繪製垂直線for(var i= stepx + 0.5; i< cxt.canvas.width; i+= stepx){ cxt .beginPath(); cxt.moveTo(i, 0); cxt.lineTo(i, cxt.canvas.height); cxt.stroke(); } //繪製橫線for(var i= stepy + 0.5; i< cxt.canvas.height; i+= stepy){ cxt.beginPath(); cxt.moveTo (0, i); cxt.lineTo(cxt.canvas.width, i); cxt.stroke(); }}drawLine(10, 10);上面範例中我們將線段繪製在兩個像素之間的像素上,而且繪製出來的線段只有0.5像素寬,
雖說canvas規範沒有明文規定,不過所有瀏覽器的Canvas實作都使用了抗鋸齒技術,以便創造出亞像素線段的繪製效果來
總結本節內容主要說明canvas中路徑中線性路徑的繪製方法,主要利用moveTo()定義起點,lineTo()定義終點,stroke()描繪當前路徑。這三個方法繪製線段
canvas中繪製路徑有兩個重要的方法,beginPath()與closePath()。繪製圖形前先呼叫beginPath()是繪製多個圖形必要的步驟。
closePath()在使用fill()時是可以省略的,而且也要注意closePath()方法的呼叫位置。
繪製線段時我們可以使用lineWidth改變線段的寬度,strokeStyle改變線段的顏色。
弄清楚線段的像素邊界,這樣我們才能繪製出真正的1像素線寬的線段。
對canvas繪製圖形有興趣的同學,請持續關注後續更新,如有不對的地方也請指出並多多交流。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。