2014年10月14日 星期二

HTML5 Canvas繪圖

    Canvas是HTML5的新元素之一,它所提供的API可讓我們動態產生顯示圖形、圖表、影像和動畫等等,以往我們要在網頁上製造出這類的效果,只能依賴Flash或Silverlight的外掛程式,但是自從HTML5出現後,我們就可以直接使用Javascript及標籤語法來繪製圖形或產生動畫效果了。
    HTML5繪製圖形的方式有兩種技術:Canvas與SVG,兩者最大的差異為Canvas是點陣圖而Canvas是向量圖形式。   

Canvas
SVG
圖形格式
點陣圖
向量圖
放大支援
放大到一定程度後會模糊
無論放大多少倍清晰度不變
處理效能
大型及複雜圖檔會導致處理速度降低及記憶體使用增加
大型及複雜圖檔對於系統效能影響不顯著
精細繪圖
可繪製較精密細緻複雜的圖形
無法針對像素操作,因此無法製作過於複雜精密的圖形
相對的Adobe工具
Illustrator
Photoshop
  Canvas並不困難,只要有基本的HTML及Javascript概念就可以很快上手,下面我們開始來示範如何使用HTML5 Canvas來進行圖形繪製,如果您有興趣的話,可以在自己的電腦安裝LAMP軟體,並且用文字編輯軟體來編寫範例中的HTML和Javascript碼來試試。
本文介紹的是Canvas基本繪圖及文字顯示,前面所使用的範例來自於http://www.html5canvastutorials.com/,這個網站對於Canvas有非常清楚的用法介紹,另外,最後一個稍複雜的圖形繪製範例則來自於http://www.williammalone.com/articles/html5-canvas-example/,這個範例使用到的技巧都是前方所介紹過的,相當適合作為練習使用;其實Canvas不僅提供繪圖功能,它還能處理影像圖片以及製作動畫,得力於Canvas,讓HTML5能夠開發出各種驚人的動態效果與遊戲,而且支援各類的手持設備,這部份留待以後再來專文介紹。  
  1. Canvas的基本用法

  要使用Canvas時,我們需先在HTML中宣告一個<canvas>標籤,然後透過Javascript針對此canvas物件進行繪製,其步驟如下:
    • 在HTML中宣告一個Canvas物件
    • 取得HTML中宣告的Canvas 我們可以想像為取得一個畫板
    • 取得Canvas的Context物件 我們可以想像為取得畫筆
    • 透過Context物件提供的方法及屬性進行繪圖 開始作畫
  • 範例:繪製矩形

   我們將繪製如下的兩個矩形

繪製矩形方式:
步驟:1.建立Canvas html 標籤 → 2.使用javascript取得Canvas物件 → 3.使用javascript取得Canvas的2D context物件 → 4.使用fillStyle屬性設定顏色 5.使用fillRect指令繪製出矩形
程式碼:(請對照上述1 ~ 5 的步驟)
 





說明:
        在上圖中,我們繪製了一紅一藍兩個矩形,其中藍色的透明度為0.5。
      1. var ctx = canvas.getContext("2d");
取得繪製2d圖形的畫筆
      1. ctx.fillStyle = "#fa1005";
設定填充的顏色 (亦可使用其它顏色的格式,如rgb(255,0,0)或直接用 red)
      1. ctx.fillRect(50,50,200,200);
畫出矩形,對角線為x,y座標軸(50,50)到(200,200)的紅色矩形,請參考下方的示意圖。
      1. ctx.fillStyle = "rgba(0,0,255,0.5)";
藍色矩形繪製方式同上,但設定填充的顏色的指令不同 (rgba(0,0,255,0.5)的第四個參數0.5指的是不透明度,1代表完全不透明)
  1. 繪製路徑:以三角形為例

所謂的路徑就是通常我們所說的「一筆繪圖」,首尾封閉的一種圖形,在下面的範例中我們以三角形為例,示範如何利用Canvas路徑繪製圖形,其它任何可以一筆畫完的封閉圖形也是如下的作法。
繪製三角形方式:
步驟:1.建立Canvas html 標籤 → 2.使用javascript取得Canvas物件 → 3.使用javascript取得Canvas的2D context物件 → 4.使用strokeStyle設定線條顏色 5.使用moveTo()將啟始點移到(x1,y1) 6.呼叫lineTo ()方法繪製直線到(x2,y2) → 7.呼叫lineTo ()方法繪製直線到(x3,y3) →8.呼叫lineTo ()方法繪製直線到(x1,y1) → 9. 呼叫stroke()將線條繪出
程式碼:(請對照上述1 ~ 7 的步驟)











執行結果:
繪製說明:
1. 啟始點移到(100,100)
2. 畫線到(300,100)
3. 再畫到(200,200)
4. 再畫到啟始點(100,100)
  1. 繪製弧形與圓形

上面介紹了繪製路徑的方法moveTo()與lineTo(),下面我們來看看繪製弧形和圓形的方法arc(),其語法如下:
        context.arc(x ,y ,半徑 ,開始角度 ,結束角度 ,是否逆時針方向)
    弧形和圓形的語法都是使用arc,兩者的差異在在於繪製圓形時只要將開始角度設為0,結束角度設為2л(或360)就可以畫出圓形。
    另外要注意的是,在arc()中的角度指的是「弧度(radian)」而不是「度(degree)」,所以我們在傳入此參數時要先利用這個轉換公式來處理:弧度=角度*Math.PI / 180
畫一個從100度順時針到230度的弧形:
   










    執行結果:
startAngle和endAngle分別改為0和360,就可以畫出圓形:
  1. 繪製拋物線

我們可以利用quadraticCurveTo()繪製二元拋物線,這個方法需要傳入四個參數:
    context.quadraticCurveTo( cpx, coy, x, y)
步驟:1. beginPath()宣佈開始繪製 2. 使用moveTo()移到啟始點 3. 使用quadraticCurveTo()繪製拋物線 3. 可透過lineWidth()及strokeStyle分別定義線寬及顏色 4. 最後使用stroke()將圖形畫出來










那如果我們要畫的是三元拋物線(貝茲曲線)呢,也很簡單,它只比起二元拋物線要多傳入一個控制點:
context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
繪製三元拋物線的步驟與二元拋物線相同,僅在於使用的函數及傳入參數有所差異:
步驟:1. beginPath()宣佈開始繪製 2. 使用moveTo()移到啟始點 3. 使用bezierCurveTo ()繪製拋物線 3. 可透過lineWidth()及strokeStyle分別定義線寬及顏色 4. 最後使用stroke()將圖形畫出來










  1. 繪製文字

Canvas除了可以繪製圖形外,亦可以繪製文字,它提供了兩種繪製文字的方式:實心及空心文字
實心文字:context.fillText( text ,x ,y ,maxWidth )
    空心文字:context.strokeText( text ,x ,y ,)
    text → 要顯示的文字
    x, y → 顯示的座標位置
    maxWidth → 此值為可選擇性輸入,若有輸入此值則文字寬度將會限制在指定的數值之內
基本上,我們只要使用上述的fillText()或strokeText()便可以將文字顯示在Canvas上了,但通常會再搭配下列常用的參數指令:
    設定字形 → context.font = 'italic 40pt Calibri';
        設定顏色 → context.fillStyle = 'blue';
        水平對齊方式 → context.textAlign = 'center';
        垂直對齊方式 → context.textBaseline = 'middle';
        使用strokeText()來顯示空心字時:
設定線條寬度:context.lineWidth = 3;
設定線條顏色:context.strokeStyle = 'blue';















步驟:1. 設定相關字形參數 2. 使用fillText()或strokeText()繪出字串
  1. 綜合練習

接下來,我們用Canvas來繪出下面這個圖形作為本單元的結束。
Step 7
A)先產生一張165x145大小的畫布:
        <canvas id="canvasId" width="165" height="145"></canvas>
B)取得Canvas 2D的context(可看成畫筆)
        var context = document.getElementById("canvasId").getContext("2d");
    C)產生一個三角形並著色
var width = 125;  //三角形的寬度
var height = 105; //三角形的高度
var padding = 20;  //三角形周圍的空白間隔

// 開始畫路徑
context.beginPath();
context.moveTo(padding + width/2, padding);        // 三角形中間的點
context.lineTo(padding + width, height + padding); // Bottom Right
context.lineTo(padding, height + padding);         // Bottom Left
context.closePath();

// 塗上顏色
context.fillStyle = "#ffc821";
context.fill();
   
        此時我們會得到如下的圖形:
Step 1
您可以看看下方的座標說明會更清楚:
    D)加上漸層效果
        我們將左側的程式碼更改為右側的內容;設定線性漸層的指令為:
createLinearGradient(x1,x1,y2,y2) 這四個參數表示我們要由(x1,y1)至(x2,y2)產生漸層效果。
addColorStop(n,Color) 指定在比例為n的位置顯示顏色為Color的漸層,其中n為介於0~1的數值。







    此時顯示的效果如下:
           
                Step 2
        E)加入陰影效果
我們要替此三角形加上陰影效果,讓它變得更立體,請加入下方的程式碼在塗上顏色程式碼區段之前
// 加入陰影效果
context.shadowBlur = 10;  // 模糊程度,此數值愈大愈模糊
context.shadowColor = "black"; // 陰影顏色
   
// 塗上顏色

            此時顯示的效果如下:
    Step 3
        E)加入第二個漸層效果
我們在原先的漸層上再加入一個漸層色可讓圖形顯得比較生動不至於太呆板;一樣也是加在塗上顏色程式碼區段之前:
// 水平的漸層,但塗色位置與原先的不同
gradient = context.createLinearGradient(0,padding,0,padding+height);
gradient.addColorStop(0.5, "transparent");
gradient.addColorStop(0.5, "#dcaa09");
gradient.addColorStop(1, "#faf100");

// 塗上顏色

            此時顯示的效果如下:
Step 4
        F)替三角形加上黑框
在下方的程式碼中,我們比較陌生的是lineJoin,這個屬性可以設定兩條線接點的形式,在此我們設定為圓邊。
// 加上黑框
context.lineWidth = 5;
context.lineJoin = "round";   
context.strokeStyle = "#333";
context.stroke();
   
        此時圖片會顯示如下:
                    Step 5
        G)替黑框再加上黃色外框
  我們接下來將黃色外框加在黑框外,會感覺黑框好像是畫在板子裏,會更有擬真的效果;其作法與黑框完全相同。
context.lineWidth = 20;
context.lineJoin = "round";   
context.strokeStyle = gradient;
context.stroke();

        此時圖片會顯示如下:















         H)加入文字:驚嘆號
最後,我們在中間區域用fillText指令來加上驚嘆號就完成了。

context.textAlign = "center";
context.textBaseline = "middle";
context.font = "bold 60px 'Times New Roman', Times, serif";
context.fillStyle = gradient;
try{
   context.fillText("!", canvasWidth/2, padding + height/1.5);
}catch(ex){}


         I)成果


沒有留言:

張貼留言