天天看點

詳解HTML5 canvas的線條及線條屬性

詳解HTML5 canvas的線條及線條屬性

今天這篇文章帶大家了解一下HTML5 canvas的線條及線條屬性。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。

詳解HTML5 canvas的線條及線條屬性

建立 canvas

首先建立一個canvas元素,我們隻需要在html檔案中加入這麼一句代碼:

<canvas id="canvas">目前浏覽器不支援canvas,請更換浏覽器使用!</canvas>      

同時我們也可以通過canvas的标簽屬性width和height設定canvas畫布的大小:

<canvas id="canvas" width="800" height="800">目前浏覽器不支援canvas,請更換浏覽器使用!</canvas>      

當然,我們也可以通過js來設定canvas的寬高,下文會提到如何設定。

接下來我們就在js中擷取到該canvas元素,然後設定它的寬高,并擷取到上下文的環境:

var canvas = document.getElementById("canvas");//擷取到canvas元素
//設定寬高
canvas.width = 800;
canvas.height = 800;
var context = canvas.getContext("2d");//擷取上下文的環境      

接下來我們的所有操作都是基于這個context的上下文環境。

現在畫一條簡單的直線:

context.moveTo(100,100);
context.lineTo(500,500);      

moveTo()方法表示一次繪制的起點坐标,lineTo()表示基于上一個坐标點到這個坐标點之間的直線連接配接。

注意的是,canvas是基于狀态的繪制,而不是基于對象的繪制。是以,上面代碼都是狀态的設定,我們還需要使用stroke()方法進行繪制:

context.stroke();//繪制      

除此之外,我們還可以設定線條的一些基本屬性:

context.lineWidth = 8;//線條的寬度
context.strokeStyle = "#333";//線條的顔色      

一個簡單的繪制一條直線的完整例子:

var canvas = document.getElementById("canvas");//擷取到canvas元素
//設定寬高
canvas.width = 800;
canvas.height = 800;
var context = canvas.getContext("2d");//擷取上下文的環境
//canvas 是基于狀态的繪制,而不是對象
context.moveTo(100,100);
context.lineTo(500,500);
context.lineWidth = 8;//線條的寬度
context.strokeStyle = "#333";//線條的顔色
context.stroke();//繪制      

運作結果如下圖:

詳解HTML5 canvas的線條及線條屬性

接下來我們繪制一個連續折線:

context.moveTo(100,100);
context.lineTo(500,100);
context.lineTo(500,500);
context.lineTo(100,500);      

運作結果如下:

詳解HTML5 canvas的線條及線條屬性

如果我們想要讓這個折線閉合形成一個矩形的話,可以再設定context.lineTo(100,100);然而如果線條的寬度比較大的時候,就會出現一些瑕疵,這個的話大家自己試試看。

是以标準的話應該使用context.closePath();這個知識點後面會講到,這裡大家可以先試試,看看運作結果是怎麼樣的。

上面這個簡單的例子我們是連續繪制的折線,也就是說可以一筆連續畫完的折線。如果是多條間斷的折線,那麼我們就需要使用context.moveTo()來重新繪制一條折線的起點坐标:

context.moveTo(100,200);
context.lineTo(300,400);
context.lineTo(100,600);


context.moveTo(300,200);
context.lineTo(500,400);
context.lineTo(300,600);


context.moveTo(500,200);
context.lineTo(700,400);
context.lineTo(500,600);      

運作結果如下:

詳解HTML5 canvas的線條及線條屬性

此時,如果我們想要繪制的這三條折線是不同顔色的,那該怎麼辦?一種常見的錯誤用法就是:

context.moveTo(100,200);
context.lineTo(300,400);
context.lineTo(100,600);
context.lineWidth = 8;
context.strokeStyle = "red";
context.stroke();//繪制context.moveTo(300,200);
context.lineTo(500,400);
context.lineTo(300,600);
context.lineWidth = 8;
context.strokeStyle = "green";
context.stroke();//繪制context.moveTo(500,200);
context.lineTo(700,400);
context.lineTo(500,600);
context.lineWidth = 8;
context.strokeStyle = "blue";
context.stroke();//繪制      

運作結果會是三條折線都是藍色的。因為這裡的第二條折線的strokeStyle屬性會覆寫第一條折線的strokeStyle屬性,而stroke()方法的執行會繪制目前所有的狀态,是以第一條折線就變成綠色。

同理,最終三條折線就都是藍色。是以呢,這裡就需要使用beginPath()方法來重新進行一次全新的繪制。

context.lineWidth = 8;//線條的寬度context.beginPath();
context.moveTo(100,200);
context.lineTo(300,400);
context.lineTo(100,600);
context.strokeStyle = "red";
context.stroke();//繪制context.beginPath();
context.moveTo(300,200);
context.lineTo(500,400);
context.lineTo(300,600);
context.strokeStyle = "green";
context.stroke();//繪制context.beginPath();
context.moveTo(500,200);
context.lineTo(700,400);
context.lineTo(500,600);
context.strokeStyle = "blue";
context.stroke();//繪制      

這裡在每繪制一條折線的時候,都使用beginPath()方法來進行一次全新的路徑繪制。此時再使用stroke()方法進行繪制的時候,就隻會繪制beginPath()方法下面的狀态。運作結果如下:

詳解HTML5 canvas的線條及線條屬性

從上面的代碼我們可以看到:context.lineWidth = 8;放在了最前面,這是因為beginPath()方法不會将沒有修改的屬性變成預設值。

比如這裡的lineWidth,三條折線都是8,那麼我們放在前面的話,在進行stroke()方法進行繪制的時候,都是會使用lineWidth = 8;來進行繪制。

而需要修改的屬性則在具體的路徑繪制裡進行修改,比如這裡的線條顔色屬性,每條折線的顔色都不一樣,是以就需要各自設定。

還有一點就是:此段代碼中的moveTo()方法可以改成lineTo()方法:

context.lineWidth = 8;//線條的寬度
context.beginPath();
context.lineTo(100,200);
context.lineTo(300,400);
context.lineTo(100,600);
context.strokeStyle = "red";
context.stroke();//繪制      

因為使用了beginPath()方法,就會對之前繪制的路徑進行清空,但不會回到(0,0)原點。是以這裡我們直接使用lineTo()方法同樣能起到繪制起點的作用,但必須和beginPath()方法一起使用才能替換moveTo()方法。

上面曾簡單講過context.closePath()方法,這裡将具體展開介紹:context.closePath()方法和context.beginPath()方法一起使用,以繪制閉合的路徑圖形,這是繪制封閉多邊形的标準做法。

而且使用context.closePath()方法,最後一條線的繪制可以省略,它會自動幫我們連接配接到繪制起點以形成封閉的多邊形。

context.beginPath();
context.moveTo(100,100);
context.lineTo(500,100);
context.lineTo(500,500);
context.lineTo(100,500);
context.closePath();
context.lineWidth = 8;
context.strokeStyle = "#333";
context.stroke();      

運作結果如下:

詳解HTML5 canvas的線條及線條屬性

接下來我們介紹一下填充屬性fillStyle和填充繪制方法fill():

context.beginPath();
context.moveTo(100,100);
context.lineTo(500,100);
context.lineTo(500,500);
context.lineTo(100,500);
context.closePath();
context.lineWidth = 8;
context.strokeStyle = "#333";
context.stroke();
context.fillStyle = "red";   //填充顔色context.fill(); //填充      

最後兩行代碼就是設定了填充的顔色(紅色)和進行閉合圖形的顔色填充,運作結果如下:

詳解HTML5 canvas的線條及線條屬性

可以看到圖形的邊框寬度比沒有填充顔色的圖形的邊框寬度小,這是因為我們先繪制邊框,再填充顔色。而實際上應該是先填充顔色,再繪制邊框。

而且fill()方法和stroke()方法的原理是一樣的,都是基于目前狀态進行繪制。

是以,為了可讀性,我們可以将屬性設定放在一起,最後在使用fill()和stroke()方法:

context.beginPath();
context.moveTo(100,100);
context.lineTo(500,100);
context.lineTo(500,500);
context.lineTo(100,500);
context.closePath();
context.lineWidth = 8;
context.strokeStyle = "#333";
context.fillStyle = "red";


context.fill(); //先填充context.stroke(); //再繪制邊框      

這次的運作結果:

詳解HTML5 canvas的線條及線條屬性

可以看到,這次的結果就是正确的了。

對于繪制矩形這個很常用,那麼我們就可以封裝成函數,友善以後調用:

drawRect(context,100,100,400,400,8,"#333","blue");


function drawRect(cxt,x,y,width,height,borderWidth,borderColor,fillColor){
    cxt.beginPath();
    cxt.moveTo(x,y);
    cxt.lineTo(x+width,y);
    cxt.lineTo(x+width,y+height);
    cxt.lineTo(x,y+height);
    cxt.closePath();
    cxt.lineWidth = borderWidth;
    cxt.strokeStyle = borderColor;
    cxt.fillStyle = fillColor;
    cxt.fill(); 
    cxt.stroke(); 
}      

同樣的,運作結果也是正常的:

詳解HTML5 canvas的線條及線條屬性

但是呢,canvas API 提供了繪制矩形更加友善的方法:rect()方法用于規劃矩形的路徑,fillRect()方法在規劃了矩形的路徑之後還填充了矩形的顔色,而strokeRect()方法則繪制了矩形的邊框。

是以上面的函數若使用context.rect()方法可以簡化為:

function drawRect(cxt,x,y,width,height,borderWidth,borderColor,fillColor){
    cxt.beginPath();
    cxt.rect(x,y,width,height);
    cxt.closePath();
    cxt.lineWidth = borderWidth;
    cxt.strokeStyle = borderColor;
    cxt.fillStyle = fillColor;
    cxt.fill(); //先填充
    cxt.stroke(); //再繪制邊框
}      

而使用fillRect()和strokeRect()這兩個方法則可以更加簡單就實作:

function drawRect(cxt,x,y,width,height,borderWidth,borderColor,fillColor){
    cxt.lineWidth = borderWidth;
    cxt.strokeStyle = borderColor;
    cxt.fillStyle = fillColor;
    cxt.fillRect(x,y,width,height);
    cxt.strokeRect(x,y,width,height);
}      

此時如果我們繪制了兩個矩形:

drawRect(context,100,100,400,400,8,"#333","blue");
drawRect(context,300,300,400,400,8,"#333","red");      

運作結果是這樣的:

詳解HTML5 canvas的線條及線條屬性

可以看到,後繪制的矩形會蓋在前繪制的矩形之上,當然得顔色不同才展現出來。

此時我們将第二個矩形的填充顔色改一下:

drawRect(context,300,300,400,400,8,"#333","rgba(255,0,0,0.5)");      

結果如下:

詳解HTML5 canvas的線條及線條屬性

可以看到第二個矩形的填充顔色是半透明的紅色。那麼就需要說明一下:fillStyle 和 strokeStyle 屬性的顔色值可以是CSS3支援的任何一種形式:

#ffffff
#333
red
rgb(0,0,0)
rgba(255,0,0,0.5)
hsl(20,50%,50%)
hsla(20,50%,60%,0.6)      

線段還有其他一些屬性,接下來分别講解:

lineCap屬性就是定義線段開頭和結尾處的形狀,此屬性有三個屬性值:butt(預設值),round,square 。

通過代碼來示範這三種效果:

context.lineWidth = 50;
context.strokeStyle = "#005588";


context.beginPath();
context.moveTo(100,200);
context.lineTo(700,200);
context.lineCap = "butt";
context.stroke();


context.beginPath();
context.moveTo(100,400);
context.lineTo(700,400);
context.lineCap = "round";
context.stroke();


context.beginPath();
context.moveTo(100,600);
context.lineTo(700,600);
context.lineCap = "square";
context.stroke();      

這裡畫了三條線段,分别設定了不同的lineCap屬性值,看看有什麼不同:

詳解HTML5 canvas的線條及線條屬性

從結果可以看出來,使用round屬性值會比預設值butt多出一個半圓的形狀包線上段的開始和結尾處,而是用square屬性值會在開始和結尾處多處半個方形,這就是它們的不同之處。

其中,round對于我們繪制一些圓角效果的圖形比較有用,但是它隻對線條的開頭和結尾處有效果,對于線段之間的連接配接處沒有作用,這點需要注意。

接下來我們來繪制一個五角星:

先看一下效果圖:

詳解HTML5 canvas的線條及線條屬性

我們要繪制一個這樣的五角星,其實就是要繪制出十個頂點,而且這十個頂點是有規律可循的:

詳解HTML5 canvas的線條及線條屬性

從這個圖可以看到,五角星的十個頂點可以分成兩組,分别在外圓和内圓上的五個頂點,通過數學公式可以得知:a是18度,b是36度,故a+b=54度,有了一個角的度數,還有大小圓的半徑,就可以根據三角函數公式求出頂點的坐标了,而且大小圓上的每個頂點之間的度數都是相差72度,那麼我們就可以使用函數來繪制這個五角星:

context.lineWidth = 10;
context.strokeStyle = "#005588";
drawStar(context,150,300,400,400,0);
context.stroke();


function drawStar(cxt,r,R,x,y,rotate){
    cxt.beginPath();
    for(var i = 0; i < 5; i++){
        cxt.lineTo(Math.cos((18 + i*72 - rotate)/180*Math.PI)*R + x,
                   -Math.sin((18 + i*72 - rotate)/180 * Math.PI)*R + y);
        cxt.lineTo(Math.cos((54 + i*72 - rotate)/180*Math.PI)*r + x,
                   -Math.sin((54 + i*72 - rotate)/180 * Math.PI)*r + y);
    }
    cxt.closePath();
}      

至于這裡面的公式,大家就自己想一下吧,其實就是正弦和餘弦函數。drawStar()方法的參數分别是上下文環境,小圓半徑,大圓半徑,偏移量x,偏移量y,旋轉角度。

最後還有兩個線條的屬性:lineJoin 和 miterLimit

lineJoin顧名思義就是線條與線條之間的連接配接方式,該屬性有三個屬性值:miter(預設值,尖角),bevel(銜接),round(圓角)。

我們基于上面的五角星的例子,分别設定不同的lineJoin屬性值,看看有什麼不同:

context.lineJoin = "bevel";      
詳解HTML5 canvas的線條及線條屬性
context.lineJoin = "round";      
詳解HTML5 canvas的線條及線條屬性

這些細微的差别還是大家自己試一下才有比較直覺的感受,更能了解其中的用法。

還有一個miterLimit屬性,這個屬性隻有當lineJoin屬性值是miter時才有用,預設值是10 。那麼它到底是什麼呢?

我們通過代碼來示範:

context.lineWidth = 10;
context.strokeStyle = "#005588";
context.lineJoin = "miter";
drawStar(context,30,300,400,400,0);
context.stroke();      

我們将小圓的半徑設定得比較小,此時我們的lineJoin是miter,即尖角。那麼結果會是怎麼樣的呢?

詳解HTML5 canvas的線條及線條屬性

可以看到它畢竟變成bevel連接配接方法了,這就是miterLimit屬性的影響,那麼它究竟怎麼計算的呢?看下圖:

詳解HTML5 canvas的線條及線條屬性

可以看到,它的計算還是比較複雜的,是以canvas給我們一個經驗值,也就是10,當然自己也可以修改miterLimit的值,得到自己想要的結果。

好的,以上就是線條的全部内容!未完待續….

本文完〜