基礎(chǔ)設(shè)置
1. 創(chuàng)建
HTML5 <canvas> 標(biāo)簽用于繪制圖像(通過腳本,通常是 JavaScript),<canvas> 元素本身并沒有繪制能力(它僅僅是圖形的容器)。
HTML: (canvas默認大小為300px*150px)
<canvas id="myCanvas" width="500" height="500"></canvas>
JavaScript:
var canvas = document.getElementById("myCanvas");
if (canvas == null || !canvas.getContext("2d")) return false;
var cd = canvas.getContext("2d");
getContext() 方法可返回一個對象,該對象提供了用于在畫布上繪圖的方法和屬性,包括在畫布上繪制文本、線條、矩形、圓形等等。
2. 陰影
shadowColor = color; //設(shè)置或返回用于陰影的顏色,默認全透明的黑色
shadowBlur = float; //設(shè)置或返回用于陰影的模糊級別,其數(shù)值并不跟像素數(shù)量掛鉤,也不受變換矩陣的影響,默認為 0
shadowOffsetX = float; //設(shè)置或返回陰影距形狀的 X 軸(水平)距離,不受變換矩陣所影響,負值表示陰影會往左延伸,正值則表示會往右延伸,默認為 0
shadowOffsetY = float; //設(shè)置或返回陰影距形狀的 Y 軸(垂直)距離,不受變換矩陣所影響,負值表示陰影會往上延伸,正值則表示會往下延伸,默認為 0
3. 線型
可以通過一系列屬性來設(shè)置線的樣式。
lineWidth = value; //設(shè)置或返回當(dāng)前的線條寬度,默認值是1.0,屬性值必須為正數(shù)
lineCap = butt | round | square; //設(shè)置或返回線條的結(jié)束端點樣式,默認為butt
lineJoin = round | bevel | miter; //設(shè)置或返回兩條線接合處(相交時創(chuàng)建的拐角)的樣式,默認為miter
miterLimit = value; //設(shè)置或返回最大斜接長度,斜接長度(交接處長度)是指線條交接處內(nèi)角頂點到外角頂點的長度
getLineDash(); //返回一個包含當(dāng)前虛線樣式,長度為非負偶數(shù)的數(shù)組
setLineDash(segments); //設(shè)置當(dāng)前虛線樣式
lineDashOffset = value; //設(shè)置虛線樣式的起始偏移量
詳解:
lineWidth:線寬是指給定路徑的中心到兩邊的粗細。換句話說就是在路徑的兩邊各繪制線寬的一半。因為畫布的坐標(biāo)并不和像素直接對應(yīng),當(dāng)需要獲得精確的水平或垂直線的時候要特別注意。
lineCap:butt表示線段端點在自己的格子內(nèi);round表示端點處加上了半徑為一半線寬的半圓; square 表示端點處加上了等寬且高度為一半線寬的方塊。
lineJoin:round表示創(chuàng)建圓角,邊角處磨圓,圓的半徑等于線寬;bevel表示創(chuàng)建斜角,一個線段內(nèi)邊與另一個線段外邊產(chǎn)生交點,兩個交點相連,去掉外部尖角部分,保留內(nèi)夾角部分;miter表示創(chuàng)建尖角,線段會在連接處外側(cè)延伸直至交于一點,延伸效果受到miterLimit 屬性的制約。
miterLimit:miter效果時,線段的外側(cè)邊緣會延伸交匯于一點上。線段直接夾角比較大的,交點不會太遠,但當(dāng)夾角減少時,交點距離會呈指數(shù)級增大。miterLimit 屬性就是用來設(shè)定外延交點與連接點的最大距離,如果交點距離大于此值,連接效果會變成了 bevel。
4. 顏色
canvas有兩種上色:圖形填充fillStyle 和圖形輪廓strokeStyle 。
fillStyle = color | gradient | pattern; //css顏色值 | 漸變(線性或放射性)| 可重復(fù)的圖片
strokeStyle = color | gradient | pattern; //css顏色值 | 漸變(線性或放射性)| 可重復(fù)的圖片
其中:
默認值是 #000000。
color 詳解:
gradient 詳解:
gradient = cd.createLinearGradient(x1, y1, x2, y2); //創(chuàng)建漸變,從漸變的起點 (x1,y1) 到漸變的終點 (x2,y2)。
gradient = cd.createRadialGradient(x1, y1, r1, x2, y2, r2); //創(chuàng)建漸變,從以 (x1,y1) 為原點,半徑為 r1 的圓,到另一個以 (x2,y2) 為原點,半徑為 r2 的圓。
創(chuàng)建出 canvasGradient 對象后,用 addColorStop 方法上色。
gradient.addColorStop(position, color); //position 參數(shù)必須是一個 0.0 與 1.0 之間的數(shù)值,表示漸變中顏色所在的相對位置。color 參數(shù)必須是一個有效的 CSS 顏色值。給同一位置設(shè)置兩種顏色,可以實現(xiàn)突變的效果。
示例:
var lingrad = cd.createLinearGradient(0,0,0,150); //新建一個漸變
lingrad.addColorStop(0, 'red'); //設(shè)置漸變起點為紅色
lingrad.addColorStop(0.5, 'blue'); //設(shè)置漸變中間點為藍色
lingrad.addColorStop(0.5, '#fff'); //設(shè)置漸變中間點突變?yōu)榘咨?lingrad.addColorStop(1, '#000'); //設(shè)置漸變結(jié)束點為黑色
cd.fillStyle = lingrad; //設(shè)置填充樣式為創(chuàng)建的漸變
cd.fillRect(0,0,100,100); //創(chuàng)建并填充矩形,矩形長寬各100,從上往下,頂點到75%處為紅色變藍色,75%處到底部為白色變黑色
cd.fillRect(0,0,150,150); //創(chuàng)建并填充矩形,矩形長寬各150,從上往下,頂點到中間為紅色變藍色,中間到底部為白色變黑色
pattern 詳解:
pattern = cd.createPattern(image, type); //image 可以是一個 Image 對象的引用,或者另一個 canvas 對象。type 必須是下面的字符串值之一:repeat,repeat-x,repeat-y 和 no-repeat。
注意:
用 canvas 對象作為 image 參數(shù)在 Firefox 1.5 (Gecko 1.8) 中是無效的。
圖案的應(yīng)用跟漸變很類似的,創(chuàng)建出一個pattern之后,賦給 fillStyle 或 strokeStyle 屬性即可。
示例:
var img = new Image(); //新建一個Image對象
img.src = 'someimage.png'; //設(shè)置Image對象的實際引用圖片地址
var pattern = cd.createPattern(img,'repeat'); //創(chuàng)建pattern
cd.fillStyle = pattern; //賦值給fillStyle屬性
cd.fillRect(0,0,100,100); //將圖片填充矩形框
注意:
與drawImage不同,這里需要確認Image對象已經(jīng)裝載完畢,否則圖案可能效果不對的。
5. 透明度
通過設(shè)置 globalAlpha 屬性或者使用一個半透明顏色作為輪廓或填充的樣式。
globalAlpha = value; //這個屬性影響到 canvas 里所有圖形的透明度,取值范圍在 0.0(完全透明)和 1.0(完全不透明)之間。 默認值是1.0。 如果數(shù)值不在范圍內(nèi),包括Infinity和NaN,無法賦值,并且globalAlpha會保持原有的數(shù)值。
注明:
少量顏色填充可以直接用rgba,不需要設(shè)置這個屬性
6. 填充規(guī)則
當(dāng)用到 fill(或者 clip和isPointinPath )時,可以選擇一個填充規(guī)則,該填充規(guī)則根據(jù)某處在路徑的外面或者里面來決定該處是否被填充,這對于自己與自己路徑相交或者路徑被嵌套的時候是有用的。
cd.fill(); //使用默認值直接填充
cd.fill("nonzero"); //非零環(huán)繞原則,是默認值
cd.fill("evenodd"); //奇偶原則
兩個原則詳解
非零環(huán)繞原則nonzero詳解:
用來判斷哪些區(qū)域?qū)儆诼窂絻?nèi)( 計算結(jié)果非0,即為路徑內(nèi) )。
* 在路徑包圍的區(qū)域中,隨便找一點,向外發(fā)射一條射線,
* 和所有圍繞它的邊相交,
* 然后開啟一個計數(shù)器,從0計數(shù),
* 如果這個射線遇到順時針圍繞,那么+1,
* 如果遇到逆時針圍繞,那么-1,
* 如果最終值非0,則這塊區(qū)域在路徑內(nèi)。
奇偶原則evenodd詳解:
* 在路徑包圍的區(qū)域中,隨便找一點,向外發(fā)射一條射線,
* 和所有圍繞它的邊相交,
* 查看相交線的個數(shù),如果為奇數(shù),就填充,如果是偶數(shù),就不填充。
繪制
1. 繪制矩形
canvas只支持一種原生的圖形繪制:矩形。所有其他的圖形的繪制都至少需要生成一條路徑。
矩形的繪制有三種方法:
fillRect( x , y , width , height ) //繪制一個填充的矩形
strokeRect( x , y , width , height ) //繪制一個矩形的邊框
clearRect( x , y , width , height ) //清空指定的矩形區(qū)域,讓去除部分完全透明
其中:
(x,y)起點 width寬 height高
2. 繪制路徑
路徑是通過不同顏色和寬度的線段或曲線相連接形成的不同形狀的點的集合。
圖形的基本元素是路徑。一個路徑,甚至一個子路徑,都是閉合的。
使用路徑繪制圖形的步驟:
①創(chuàng)建路徑起始點;
②使用畫圖命令去畫出路徑;
③把路徑封閉;
④路徑生成后,通過描邊或填充路徑區(qū)域來渲染圖形。
使用路徑繪制圖形的函數(shù):
beginPath() //新建一條路徑,生成之后,圖形繪制命令被指向到路徑上生成路徑
closePath() //閉合路徑之后圖形繪制指令又重新指向到上下文中
stroke() //通過線條來繪制圖形輪廓,不會自動閉合沒有閉合的形狀
fill() //通過填充路徑的內(nèi)容區(qū)域生成實心的圖形,自動閉合所有沒有閉合的形狀,不需要調(diào)用closePath()函數(shù)
moveTo( x , y ) //移動筆觸,將筆觸移動到指定的坐標(biāo)(x , y)上
lineTo( x , y ) //繪制一條從當(dāng)前位置到指定的位置(x , y)的直線
弧線
arc( x , y , radius , startAngle , endAngle , anticlockwise) //畫一個以(x , y)為圓心,以radius為半徑的圓?。▓A),從startAngle 開始到endAngle 結(jié)束,anticlockwise參數(shù)為一個布爾值,true表示逆時針,false表示順時針。
注意:
arc()函數(shù)中的角度單位是弧度,不是度數(shù)。角度與弧度的js表達式:弧度= 角度 * Math.PI / 180,角度 = 弧度 * 180 / Math.PI
貝塞爾(bezier)以及二次貝塞爾
quadraticCurveTo( cp1x , cp1y , x , y ) //繪制二次貝塞爾曲線,(x , y)為結(jié)束點,(cp1x , cp1y)為控制點
bezierCurveTo( cp1x , cp1y , cp2x , cp2y , x , y ) //繪制三次貝塞爾曲線,(x , y)為結(jié)束點,(cp1x , cp1y)為控制點一 ,(cp2x , cp2y)為控制點二
矩形
rect( x , y , width , height ) //繪制一個左上角坐標(biāo)為(x , y),寬為width高為height的矩形
Path2D對象(詳情)
new Path2D() //空的Path對象
new Path2D(path) //克隆Path對象
new Path2D(d) //從SVG建立Path對象
說明:
Path2D對象用來緩存或記錄繪畫命令,用以快速回顧路徑
例子:
var path = new Path2D();
path.rect(50,50,50,50);
cd.stroke(path);
3. 繪制文本
屬性設(shè)置:
font = value //設(shè)置或返回文本內(nèi)容的當(dāng)前字體屬性。 使用和 CSS font 屬性相同的語法,默認的字體是 10px sans-serif。
textAlign = value // 設(shè)置或返回文本內(nèi)容的當(dāng)前對齊方式??蛇x的值包括:start, end, left, right or center。 默認值是 start。
textBaseline = value //設(shè)置或返回在繪制文本時使用的當(dāng)前文本基線。 可選的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默認值是 alphabetic。
direction = value //文本方向??赡艿闹蛋ǎ簂tr, rtl, inherit。默認值是 inherit。
渲染文本:
fillText(text, x, y [, maxWidth]) //在指定的(x,y)位置填充指定的文本,繪制的最大寬度是可選的。
strokeText(text, x, y [, maxWidth]) //在指定的(x,y)位置繪制文本邊框,繪制的最大寬度是可選的。
測量文本:
measureText() //返回包含指定文本寬度的TextMetrics對象,詳解見備注。
注:
measureText()使用
TextMetrics對象詳解
4. 繪制圖像
canvas可以用于動態(tài)的圖像合成或者作為圖形的背景。瀏覽器支持的任意格式的外部圖片都可以使用,比如PNG、GIF或者JPEG,也可以將同一個頁面中其他canvas元素生成的圖片作為圖片源。
引入圖像到canvas的基本操作:
獲得一個指向HTMLImageElement的對象或者另一個canvas元素的引用作為源,也可以通過提供一個URL的方式來使用圖片,使用drawImage()函數(shù)將圖片繪制到畫布上。
canvas的API可以使用下面這些類型中的一種作為圖片的源:
HTMLImageElement //由Image()函數(shù)構(gòu)造出來的圖片,或者任何的<img>元素
HTMLVideoElement //用一個HTML的 <video>元素作為圖片源,可以從視頻中抓取當(dāng)前幀作為一個圖像
HTMLCanvasElement //用另一個 <canvas> 元素作為圖片源。
ImageBitmap //一個高性能的位圖,可以低延遲地繪制,它可以從上述的所有源以及其它幾種源中生成。
注:這些源統(tǒng)一由 CanvasImageSource類型來引用。
①使用相同頁面內(nèi)的圖片
通過下列方法的一種來獲得與canvas相同頁面內(nèi)的圖片的引用:
document.images集合
document.getElementsByTagName()方法
document.getElementById()獲得指定圖片
②使用其它域名下的圖片
在 HTMLImageElement上使用crossOrigin屬性,可以請求加載其它域名上的圖片。如果圖片的服務(wù)器允許跨域訪問這個圖片,那么你可以使用這個圖片而不污染canvas,否則,使用這個圖片將會污染canvas。
注:污染canvas詳解
③使用其它 canvas 元素
和引用頁面內(nèi)的圖片類似地,用 document.getElementsByTagName 或 document.getElementById 方法來獲取其它 canvas 元素。但你引入的應(yīng)該是已經(jīng)準(zhǔn)備好的 canvas。
④由零開始創(chuàng)建圖像
用腳本創(chuàng)建一個新的 HTMLImageElement 對象。使用Image()構(gòu)造函數(shù)。
var img = new Image(); // 創(chuàng)建一個<img>元素
img.src = 'myImage.png'; // 設(shè)置圖片源地址
當(dāng)腳本執(zhí)行后,圖片開始裝載。
若調(diào)用 drawImage 時,圖片沒裝載完,那什么都不會發(fā)生(在一些舊的瀏覽器中可能會拋出異常)。因此應(yīng)該用load事件來保證不會在加載完畢之前使用這個圖片:
var img = new Image(); // 創(chuàng)建img元素
img.onload = function(){
// 執(zhí)行drawImage語句
}
img.src = 'myImage.png'; // 設(shè)置圖片源地址
注:如果只用到一張圖片,如上操作。如果需要不止一張圖片,則應(yīng)使用圖片預(yù)加載策略。
⑤通過 data: url 方式嵌入圖像
可以通過 data:url 方式來引用圖像。Data urls 允許用一串 Base64 編碼的字符串的方式來定義一個圖片。
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
優(yōu)點是圖片內(nèi)容即時可用,無須再到服務(wù)器兜一圈,可以將 CSS、JavaScript、HTML 和 圖片全部封裝在一起,遷移方便。
缺點就是圖像沒法緩存,圖片較大時,內(nèi)嵌的 url 數(shù)據(jù)會相當(dāng)長:
⑥使用視頻幀
可以使用<video> 中的視頻幀(即便視頻是不可見的)。HTMLVideoElement對象可以作為canvas圖片源。
獲得源圖對象后,可以使用 drawImage 方法將它渲染到 canvas 里。drawImage 方法有下面三種形態(tài):
drawImage(image, x, y) //其中image 是 image 或者 canvas 對象,x 和 y 是其在目標(biāo) canvas 里的起始坐標(biāo)。SVG圖像必須在 <svg> 根指定元素的寬度和高度。
drawImage(image, x, y, width, height) //這個方法多了2個參數(shù):width 和 height,這兩個參數(shù)用來控制 當(dāng)向canvas畫入時應(yīng)該縮放的大小
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) //第一個參數(shù)和其它的是相同的,都是一個圖像或者另一個 canvas 的引用。其它8個參數(shù),前4個是定義圖像源的切片位置和大小,后4個則是定義切片的目標(biāo)顯示位置和大小。