canvas基礎學習(一)


一、概述

canvas它和其它的HTML5標簽的使用基本一致,但是它相當於在瀏覽器中建立一個畫布,可以再這個畫布上畫圖、創建動畫甚至是3D游戲。由於canvas要適配不同終端的分辨率,所以盡可能的在標簽內設置高度和寬度,這個也符合W3C的標准。代碼格式如下,當瀏覽器不支持canvas標簽的時候,會顯示其中的文字。

<canvas id="main" width="800" height="600" >
    親,您的瀏覽器不支持canvas
</canvas>

而在canvas的坐標體系中,是以左上角為坐標原點,向右為x軸正方向,向下為y軸正方向,如下圖

而在canvas中,進行繪制需要首先獲取canvas的上下文環境context,而后調用API進行圖像的繪制

var canvas = document.getElementById("main"),
    ctx = canvas.getContext("2d");

 

二、線條的繪制和填充

在canvas中,各個圖像繪制代碼可以通過beginPath()和closePath()這兩個函數進行包裹,主要用於分割各個畫圖,表示開始和結束。線條的繪制主要調用方法是moveTo(x,y)、lineTo(x,y)、stroke()、arc()、arcTo()、fill(),使用的屬性包括lineWidth、lineCap、lineJoin、strokeStyle、fillStyle等。

1、畫出邊角為圓角的一條線段

ctx.beginPath();
ctx.strokeStyle = "black";
ctx.lineWidth = 6;
ctx.lineCap = "round";
ctx.moveTo(400,400);
ctx.lineTo(600,400);
ctx.stroke();
ctx.closePath();

效果圖為:

其中strokeStyle表示線條的顏色,lineWidth表示線條的寬度,lineCap設置線條的邊緣為圓角,lineCap的屬性有butt|round|square,第一個是默認值表示平直的邊緣,round為圓角,square為正方的邊緣。moveTo(x,y)表示划線的起點為(x,y)坐標,而lineTo(x,y)設置線條的終點為(x,y),最后通過調用stroke()方法進行繪制。

2、畫出兩條線段,焦點為圓角

ctx.beginPath();
ctx.strokeStyle = "black";
ctx.lineWidth = 10;
ctx.lineJoin = "round";
ctx.moveTo(400,500);
ctx.lineTo(600,500);
ctx.lineTo(600,600);
ctx.stroke();
ctx.closePath();

效果圖為:

和上面的demo的不同點在於使用的屬性為lineJoin,同樣它也有三個屬性bevel|round|miter,第一個是默認值表示斜角,而miter表示尖角。同時lineTo(x,y)可以調用多次,進行線段的繪制,所以可以通過moveTo()和lineTo()這兩個方法進行多邊形的繪制

3、矩形的繪制並填充顏色

ctx.beginPath();        
ctx.moveTo(50,50);
ctx.lineTo(100,50);
ctx.lineTo(100,100);
ctx.lineTo(50,100);
ctx.lineTo(50,50);
ctx.lineWidth = 4;
ctx.strokeStyle = "red";
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();
ctx.closePath();

效果圖為:

通過moveTo()和lineTo()方法進行多邊形的繪制后,得到了一個閉合區間,就可以調用fill()方法對其中的顏色進行填充,fillStyle則是設置閉合區間內的顏色。如果不用stroke()方法,也就是不繪制外邊框的線條,則可以省去最后的那個回到起點的方法ctx.lineTo(50,50),因為fill()會自動將起點和終點進行連接得到一個閉合區間。

 

如果是單純的矩形而非不規則的多變型的時候,可以直接調用canvas的api方法strokeRect(x,y,w,h)和fillRect(x,y,w,h);前兩個參數表示起點的坐標,后兩個表示矩形的寬度和高度。

ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = "darkgray";
ctx.strokeRect(50,50,200,100);
ctx.closePath();

ctx.beginPath();
ctx.fillStyle = "coral";
ctx.fillRect(300,50,200,100);
ctx.closePath();

效果圖為:

 

4、弧形的繪制

首先是arc(x,y,r,beginPi,endPi,anticlockwise)函數,前兩個參數表示圓心的x,y坐標,中間的那個r表示圓的半徑,后兩個參數表示起始弧度和結束弧度,最后表示是否是逆時針繪制,默認是false即順時針繪制。在canvas中,無論是順時針還是逆時針,圓的弧度都是一個定值,如下圖:

ctx.beginPath();
ctx.arc(320,200,50,0,Math.PI*2);
ctx.lineWidth = 3;
ctx.strokeStyle = "black";
ctx.stroke();
ctx.fillStyle = "chartreuse";
ctx.fill();
ctx.closePath();

效果圖為:

 

還可以通過arcTo(x1,y1,x2,y2,r);繪制圓弧,它與moveTo(x,y)一起進行使用,(x,y)(x1,y1)與(x1,y1)(x2,y2)以這兩條線段為切線,繪制半徑為r的圓弧,起點和終點為那兩個切點。

ctx.beginPath();
ctx.lineTo(400,200);
ctx.arcTo(500,200,500,300,100);
ctx.strokeStyle = "aqua";
ctx.stroke();
ctx.closePath();

效果圖為:

最后就是貝塞爾曲線繪制曲線,由於數學算法比較復雜,也沒有過多研究

a、二次貝塞爾曲線

cxt.quadraticCurveTo(x1,y1,x2,y2);

同樣是與 cxt.moveTo(x0,y0);混用,其是通過(x1,y1)為控制點畫圓弧

http://blogs.sitepointstatic.com/examples/tech/canvas-curves/quadratic-curve.html

該網址是二次貝塞爾曲線的測試網址

b、三次貝塞爾曲線

cxt.bezierCurveTo(x1,y1,x2,y2,x3,y3);

同樣是與 cxt.moveTo(x0,y0);混用,其是通過(x1,y1),(x2,y2)為控制點畫圓弧 

http://blogs.sitepointstatic.com/examples/tech/canvas-curves/bezier-curve.html

該網址是三次貝塞爾曲線的測試網址 

(ps:其中三次曲線比二次曲線好用,他可以繪制會各種突出弧形以及波浪)

 

三、圖形變換

 無論哪種語言處理圖像時,都有一個思想。那就是先確定好圖形畫法函數,然后通過圖形變換函數將圖形進行位移、旋轉角度、大小的改變。

在canvas中,由於canvas是一種基於狀態的編程,所以之前提到在繪制點與點之間的直線以及顏色時使用

context.beginPath();

context.closePath();

這兩個函數可以將點與點之間的函數的狀態進行隔離,並且還可以完成封閉的圖形,即首尾點會自動連接

而在圖形變換中也需要這樣的規范寫法,它們分別是

context.save();

context.restore();

通過這兩個函數將函數變換的函數隔離開

1、translat

context.translat(x,y)

它是將圖像進行平移,x是水平方向平移的距離,y是垂直方向平移的距離

ctx.save();
ctx.translate(50,50);
ctx.beginPath();
ctx.strokeRect(10,10,20,20);
ctx.closePath(); 
ctx.restore();

效果圖為:

本來這個矩形應該繪制在左上角,經過圖形變換把其向x,y兩個方向各偏移了50像素(PS:需要注意的是圖形變換的函數調用,要在繪制函數之前執行)

 

2、rotate

context.rotate(rot);

該方法是用來設置圖片的旋轉角度,其中rot應該是弧度,若傳入的是角度的話需要轉換,如80,需要些為Math.PI*80/180

ctx.save();
ctx.rotate(20*Math.PI/180);
ctx.beginPath();
ctx.fillRect(100,100,50,50);    
ctx.closePath();
ctx.restore();

效果圖為:  向順時針方向偏移了20度

 

3、scale

context.scale(x,y)

該方法是用來進行圖像縮放的,其中x為水平方向縮放的比例,y是垂直方向縮放的比例

(PS: 該函數存在一個問題,就是在縮放時,圖像的左上角的位移也會發生同樣比例的改變並且圖像的邊框線也會發生同樣的改變

ctx.save();
ctx.scale(0.5,0.5);
ctx.beginPath();
ctx.fillRect(100,100,200,200);    
ctx.closePath();
ctx.restore();

就是將正方形的x和y方向均縮放到一半的大小

4、transform

context.transform(a,b,c,d,e,f);

首先該方法是上述方法的總和,因為該方法是通過單位矩陣的方式對圖像進行改變,圖像在本質上就是許多由0,1的矩陣組合而成,如下表格

a c e
b d f
0 0 1

 

a代表水平縮放,默認為1;b代表水平傾斜,默認為0;c代表垂直傾斜,默認為0;

d代表垂直縮放,默認為1;e代表水平位移,默認為0;f代表垂直位移,默認為0;

所以用transfrom函數可以實現,上面3種圖像變換。

 

四、其它雜七雜八

1、文字顯示

ctx.fillText(string,x,y,[maxlen]);

ctx.strokeText(string,x,y,[maxlen]);

其中第一個函數是需要寫出的文本值,其中x,y是文本的坐標。而maxlen是可選參數,設置其文字的最大長度。

其文字可以設置相關參數

ctx.font的默認值是"20px sans-serif"

其參數包括context.font = font-style font-variant font-weight

font-size font-family其中各個參數有個字的值

context.textAlign = left center right該屬性是設置文字的居中、居左、居右

context.textBaseline = top middle bottom該屬性是設置文字的垂直居上、居中、居下。

ctx.beginPath();
var str = "古月楓"
ctx.strokeStyle = "red";
ctx.fillStyle = "aqua";
ctx.font = "40px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.strokeText(str,100,100,200);
ctx.fillText(str,100,150,200);
ctx.closePath();

效果圖為:

 

2、陰影

在canvas中並沒有一個針對陰影的函數,它是通過狀態進行添加,無論是線條、矩形、圓或者是文字都可以通過以下函數添加陰影效果

ctx.shadowColor = "gray";    //設置陰影背景的顏色

ctx.shadowOffsetX = 10;    //設置陰影x軸方向的突出像素,該值可以為負數

ctx.shadowOffsetY = 10;    //意思同上,只不過這個是針對Y軸的

ctx.shadowBlur = 5;    //設置陰影的模糊程度,0為無模糊,值越大模糊越重

ctx.beginPath();
var str = "古月楓"
ctx.fillStyle = "aqua";
ctx.font = "40px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.shadowColor = "gray";    
ctx.shadowOffsetX = 5;    
ctx.shadowOffsetY = 5;   
ctx.shadowBlur = 3; 
ctx.fillText(str,100,150,200);
ctx.closePath();

效果圖為:

 

3、全局變量,透明度

ctx.globalAlpha設置全局的透明度,它的默認值為1,而將其改變為0到1的值時,畫布上的圖形就有了透明效果。由其作用范圍為全局,所以要用save()和restore()方法進行包裹使用

 

4、剪輯 ctx.clip();

這個功能只有上面所說的一個函數,它是與lineTo、fillRect、arc等可繪制閉合空間的函數混用,其用處是為了canvas只能在一個封閉的空間內進行繪制,超出這個空間的圖形繪制不顯示,比較常用的運用方式是制作探照燈的效果。

ctx.save();
ctx.beginPath();
ctx.arc(200,200,100,0,Math.PI*2);
ctx.clip();
ctx.fillStyle = "chartreuse";
ctx.fillRect(100,100,200,200);
ctx.closePath();
ctx.restore();

效果圖為:

先定義了一個圓形的剪輯區域,然后畫了一個大范圍的正方形,但是只能顯示這個圓形范圍的圖像

 

5、交互

由於在canvas中整個canvas是作為一個畫布,而且其中畫出的各種圖形都無法將其作為一個對象通過事件綁定的形式進行交互,所以在canvas中的事件綁定是直接綁定在canvas上,然后通過對用戶在canvas畫布上操作的坐標的判斷進行交互。

其中最基本的方法如下

a、對canvas標簽進行事件綁定,JS以及jQuery都成

b、獲取在畫布上用戶操作的坐標

var x = event.clientX - canvas.getBoundingClientRect().left;

var y = event.clientY - canvas.getBoundingClientRect().top;

它是通過計算用戶在整個頁面的操作坐標與canvas在頁面的左上邊距進行計算的

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM