DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> HTML基礎知識 >> HTML5教程 >> canvas API ,通俗的canvas基礎知識(二)
canvas API ,通俗的canvas基礎知識(二)
編輯:HTML5教程     

上文我們講到了畫一條線,畫矩形,寫文字,總算是有了一個好的開頭,如果還沒有看的同學出門左轉,先看看那篇,這裡就不多做敘述了,接下來我們看比較復雜的一些屬性和方法!

講之前呢,我還是想溫習一下,畢竟上文還有幾個屬性沒有講到,那我們從畫三角形開始吧!

如果看了上文,機智的少年肯定會想到,三角形,多簡單啊,無非是比直線多一個點,於是這少年就開始動手了:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.stroke();

呀呵,怎麼是一個折線,三角形不是只有三個點嗎?是不是因為沒有閉合呢?那我再加一個點:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.lineTo(50,50);
ctx.stroke();

哈哈,果然機智如你啊!這個思路其實是正解的,三角形就是這麼簡單,其實還有一種方式可以畫三角形,只需3個點,那就是我們要介紹的:

closePath() 閉合路徑

有閉合就是開始,一般來說他們是成雙成對的

beginPath() 開始路徑

這對活寶的用法一般是:

ctx.beginPath();

ctx.closePath();

先開始路勁,裡面寫你要繪制的內容,然後結束路勁,相當於是一個盒子已經封箱了,這樣做有個好處就是可以避免繪制過程中的樣式污染,你不知道怎麼污染?好吧,看下面:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//第一個三角
ctx.strokeStyle = 'red';
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.lineTo(50,50);
ctx.stroke();
//第二個三角
ctx.strokeStyle = 'green';
ctx.moveTo(150,50);
ctx.lineTo(200,100);
ctx.lineTo(150,200);
ctx.lineTo(150,50);
ctx.stroke();

如圖,如果我本來是想讓第一個三角的顏色為紅色,第二個為綠色,但是現在的結果卻都是綠色,而且眼尖的同學還看到,第一個三角感覺有2個顏色,顏色也特別的深,感覺是疊了2個三角,你沒看到?好,我們改改,你在看:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//第一個三角
ctx.strokeStyle = 'red';
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.lineTo(50,50);
//ctx.stroke();
//第二個三角
ctx.strokeStyle = 'green';
ctx.moveTo(150,50);
ctx.lineTo(200,100);
ctx.lineTo(150,200);
//ctx.lineTo(150,50);
ctx.stroke();

我們先不畫第一個三角,也不畫第二個三角的左邊一邊,然後看一下:

第一個三角沒有雙重色了,說吧繪制了2次,一次紅,一次綠,去掉了重繪,後面的顏色也將前面的顏色污染了,這不是我們想要的,這污染,你應該明白了吧!

那我們使用那對活寶看看:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        //第一個三角
        ctx.beginPath();
        ctx.strokeStyle = 'red';
        ctx.moveTo(50,50);
        ctx.lineTo(100,100);
        ctx.lineTo(50,200);
        ctx.lineTo(50,50);
        ctx.closePath();
        ctx.stroke();
        //第二個三角
        ctx.beginPath();
        ctx.strokeStyle = 'green';
        ctx.moveTo(150,50);
        ctx.lineTo(200,100);
        ctx.lineTo(150,200);
        ctx.lineTo(150,50);
        ctx.closePath();
        ctx.stroke();

這才是我們想要的嘛,你玩你的,我玩我的,互不干擾,(你說畫三角只需3個點的呢,吹牛B吧,你看你都是用的4個點),哦,對。

closePath() 方法創建從當前點到開始點的路徑,這是對此方法的描述,也就是說,使用這個方法,就能將畫筆移到beginPath()的位置,這樣才能結束畫布,所以照這個理論,當畫三角時,畫到第三個點時,我們用closePath()方法讓畫筆回到起點,再畫線,是不是就閉合了,看看效果:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.closePath();
ctx.stroke();

看,只有三個點,不是折線吧,後面要講的什麼扇形圖,不規則圖形都可以用此技能,妥妥的!

嗨,也不過如此,你這線條都是一像素的,又不能跟孫悟空的金箍棒一樣,要大變大,要小變小,哼,誰說的,哥有神器在手,天下無敵!

我的法寶就是:

lineWidth  設置或返回當前的線條寬度

怎麼用?哥給一個跟金箍棒:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var timer = null;
        var num = 1;
        ctx.moveTo(150,50);
        ctx.strokeStyle = 'gold';
        setInterval(function(){
            if(num == 100){
                clearInterval(timer);
                num=1;    
            }else{
                num++;    
            };
            ctx.lineTo(150,100+num*2);
            ctx.lineWidth = num;
            ctx.stroke();
        },100)

金箍棒,大,大,大,大,在大點,哈哈哈~~~

咳咳,嚴肅點,有此神器,我們就可以修改任何線框,線條的線條寬度了,比如說空心三角形,空心矩形,當然,空心文字你就不要問我了,我不知道~

 關於線條,還有另外2個屬性:

lineJoin  兩線交叉的拐角類型

參數:

miter : 尖角 默認

bevel : 斜角

round : 圓角

什麼意思,那就用空心矩形為例:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth = 10;
ctx.beginPath();
ctx.lineJoin = 'miter';
ctx.strokeRect(100,10,80,80);
ctx.closePath();
ctx.beginPath();
ctx.lineJoin = 'round';
ctx.strokeRect(100,110,80,80);
ctx.closePath();
ctx.beginPath();
ctx.lineJoin = 'bevel';
ctx.strokeRect(100,210,80,80);
ctx.closePath();

   

右側為折線效果

配合折線效果,還有一個屬性:

miterLimit 規定最大斜接長度。什麼意思?看看右邊的這個折線圖,最下面那組的尖尖角,這個就是斜接,意思通俗意思就是規定那個尖尖角的長度,如果尖尖角的長度小於miterLimit 的值,則正常顯示,如果大於的話,就會被截掉一部分,其形狀就跟lineJoin='bevel'一樣一樣的,且此方法只對lineJoin="miter" 默認值的時候才起作用,給個形象的例子吧:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth=10;
ctx.lineJoin="miter";
ctx.beginPath();
ctx.miterLimit=19;
ctx.moveTo(20,20);
ctx.lineTo(150,27);
ctx.lineTo(20,34);
ctx.stroke();
        
ctx.beginPath();
ctx.miterLimit=18;
ctx.moveTo(20,120);
ctx.lineTo(150,127);
ctx.lineTo(20,134);
ctx.stroke();

  ctx.beginPath();
  ctx.lineJoin="bevel";
  ctx.moveTo(20,220);
  ctx.lineTo(150,227);
  ctx.lineTo(20,234);
  ctx.stroke();

 

 

如圖,當miterLimit 的值大於等於19時,尖尖角正常顯示,小於18時,尖尖角被截斷了,效果跟設置lineJoin='bevel'是一樣的,暫不知道會有什麼作用,待以後來發掘!

 

另一個:

lineCap  設置或返回線條的結束端點樣式  注意,這是設置線條的哦!

參數:

butt 默認。向線條的每個末端添加平直的邊緣。

round  向線條的每個末端添加圓形線帽。

square 向線條的每個末端添加正方形線帽。

什麼意思?線條嘛,我們還是以金箍棒為例,算了,還是用線條吧(看到金箍棒我就想笑了);

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        ctx.lineWidth = 10;
        ctx.beginPath();
        ctx.lineCap = 'butt';
        ctx.moveTo(50,50);
        ctx.lineTo(200,50);
        ctx.stroke();
        
        ctx.beginPath();
        ctx.lineCap = 'round';
        ctx.moveTo(50,100);
        ctx.lineTo(200,100);
        ctx.stroke();
        
        ctx.beginPath();
        ctx.lineCap = 'square';
        ctx.moveTo(50,150);
        ctx.lineTo(200,150);
        ctx.stroke();

可以看到,後面2個比第一個要長一點,具體長多少呢?畫一個圖示意一下:

圓角和方腳的原理其實是這樣的,很明顯多出的一部分的寬度就是線條的一半的長度,所以要精確計算其長度,此小細節需謹記!

 

現在我們來講講畫圓及其相關的圖形:

arc(x,y,r,sAngle,eAngle,counterclockwise)

什麼意思? x,y表示坐標點表示圓心坐標,r表示半徑,sAngle表示開始弧度,eAngle表示結束弧度,counterclockwise表示順時針還是逆時針方式,默認為順時針false,逆時針為true

注意,這裡的角度是用弧度表示的,不是直接寫角度,那問題來了,一般我們知道一個圓弧是多少度,怎麼知道它是多少弧度呢?總感覺弧度太抽象,嗯嗯,我也有同感,那我們就來科普一下弧度的算法吧,列幾個公式(初中,高中的數學,都還給老師了):

1弧度 = r;

360° = 2∏;

周長C = 2∏r;

那麼一周的弧度數 = 2∏r/r = 2∏ = 360° 

則1°  =  2∏*1°/360° = ∏*1° /180° (弧度)

90°  =  ∏*90° /180° (弧度)

圓的初始位置是在最右邊,跟我們自己手繪圓的起點有那麼一點點的不一樣,默認是順時針方向,那角度就應該是如圖所示的角度,要是還不清楚的話,我們畫2半圓,分別表示順時針和逆時針,這樣就應該清楚了,哦,需要說明的一點就是,畫用的方法跟畫直線和矩形框的原理是一樣的,只是畫出了路徑,並沒有添墨水,仍需用黑白雙煞:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(80,100,50,0,180*Math.PI/180,false);       
ctx.stroke();
ctx.beginPath(); ctx.arc(200,100,50,0,180*Math.PI/180,true); ctx.stroke();

 

js裡面是沒有∏的,你懂的,但是有函數Math.PI,咦,這裡為什麼是圓弧而不是半圓啊,如果我要畫一個半圓怎麼弄呢?哈哈~,還記得上面三角形的那個折線嗎?這個是一個原理,只是圖形沒有閉合而已,用closePath()就可以閉合了。

畫一個扇形看看,這裡我就閉合圖形哈:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(80,100,50,30*Math.PI/180,150*Math.PI/180,false);
ctx.closePath();
ctx.stroke();

 

當當當當~~~

噗,噴了一口老血,怎麼是一條小船,說好的扇子呢?再看看三角圖形,瞬間就明白了,圖形閉合不是以圓心為起始點的,而是初始弧度為起點,然後閉合的時候是回到初始點,就變成小船了,那怎麼才能畫出一個扇形呢?給個思路,這裡暫時不給代碼,以後有時間當小實例給到大家,如果我以圓心為起點,畫2條直線,連到圓弧的起始點和結束點,是不是就是一個扇形了,哈哈~,不多說了,腦補一下吧,當然,圓弧的起始點的坐標和結束點的坐標計算還是有點費勁的

前面我們畫的是空心的圓或弧,可否畫實心的呢?貌似問的有點多余,上面說了用黑白雙煞,好吧,直接給個一餅好了:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.arc(150,150,50,0,360*Math.PI/180,false);
ctx.fill();

咦,怎麼這麼像某島國國旗,還好我用的是默認黑色,噓噓,都沒看到哈~

還有一個方法可以畫圓弧:

arcTo(x1,y1,x2,y2,r) 創建兩個切線之間的弧/曲線

參數:x1,y1 表示第一個坐標,x2,y2表示第二個坐標,r表示曲線半徑

兩個切線之間的曲線,試試:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);          
ctx.lineTo(100,20);          
ctx.arcTo(150,20,150,70,50); 
ctx.lineTo(150,120);        
ctx.stroke();  

果然是要在兩條線段之間寫曲線, 要是先寫2條曲線,在寫arcTo(),貌似就出不來了,這讓我們想到了moveTo(),lineTo(),再寫一個例子:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.moveTo(150, 20);
ctx.arcTo(150,200,50,0,20);
ctx.stroke();

 

想試一下,要是只有一條切線,會怎樣?

好大的一個魚鉤啊,看來這樣也是可以的,要是沒有切線,可否?

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.arcTo(150,200,50,0,20);
ctx.stroke();

 

額,狗帶了,沒反應,看來必須至少有一個切線才能畫弧線,有個點都行,要求不算高,滿足你。

感覺這裡始終沒有將清楚,arcTo()為什麼會畫出這樣的曲線呢,我覺得有必要畫一張圖來表示:

    

它的繪圖原理應該是這樣的,起始點是圓弧的第一個切點,也是畫筆的起始點,然後arcTo的兩個坐標點分別是圓弧的起點和終點,這樣3個點就形成了2天相交的線,然後以半徑為r畫一個圓,與這2條線相切,2個切點就是繪制的這條弧,而第二張圖就是arcTo()所繪制的圖形,為了證實這一點,我們寫一個相近的圖形來看看:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.fillRect(100,100,5,5);
ctx.fillRect(180,80,5,5);
ctx.fillRect(160,180,5,5);
ctx.moveTo(62,112);
ctx.lineTo(182,82);
ctx.lineTo(162,182);
//這裡是繪制切線弧        
ctx.moveTo(103,103);
ctx.arcTo(183,83,162,182,40);
ctx.stroke();

      

對比這2組圖,將生成的弧線用圓對比一下,會發現起點並不是切點,但基本思路是正確的,3點形成一個夾角,然後以r為圓心,畫一個圓,從起點到第二個切點,就是arcTo()方法所繪制的圖形。

 

今天就到這吧!講的很混亂,東一腳西一腳的,希望你們能懂!最希望的是能對你們有幫助,那就再好不過了!

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved