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()的用法
#moveTo(x,y): 將筆觸移到指定的座標x以及y上,在目前路徑中增加一條子路徑,該方法不會清除目前路徑中的任何子路徑。
lineTo(x,y): 繪製一條從目前位置到指定x以及y位置的直線,如果目前路徑中沒有子路徑,那麼這個方法的行為與moveTo()一樣。 如果目前路徑中存在子路徑,此方法會將你所指定的這個點加入子路徑中。
改變線段的樣式
#改變線段的寬度
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.addColorStop(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(); }
修改上面例子中的代码在代码中添加beginPath()与closePath()方法
cxt.strokeStyle = 'green'= 250, 5050, 150150, 150150, 250 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像素線寬的線段。
以上是如何繪製路徑-線段的詳細內容。更多資訊請關注PHP中文網其他相關文章!