基礎(chǔ)設(shè)置
1. 創(chuàng)建
HTML5 <canvas> 標(biāo)簽用于繪制圖像(通過腳本瓢喉,通常是 JavaScript)宁赤,<canvas> 元素本身并沒有繪制能力(它僅僅是圖形的容器)。
HTML: (canvas默認(rèn)大小為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() 方法可返回一個(gè)對(duì)象栓票,該對(duì)象提供了用于在畫布上繪圖的方法和屬性决左,包括在畫布上繪制文本、線條走贪、矩形佛猛、圓形等等。
2. 陰影
shadowColor = color; //設(shè)置或返回用于陰影的顏色坠狡,默認(rèn)全透明的黑色
shadowBlur = float; //設(shè)置或返回用于陰影的模糊級(jí)別继找,其數(shù)值并不跟像素?cái)?shù)量掛鉤,也不受變換矩陣的影響逃沿,默認(rèn)為 0
shadowOffsetX = float; //設(shè)置或返回陰影距形狀的 X 軸(水平)距離婴渡,不受變換矩陣所影響,負(fù)值表示陰影會(huì)往左延伸凯亮,正值則表示會(huì)往右延伸边臼,默認(rèn)為 0
shadowOffsetY = float; //設(shè)置或返回陰影距形狀的 Y 軸(垂直)距離,不受變換矩陣所影響假消,負(fù)值表示陰影會(huì)往上延伸柠并,正值則表示會(huì)往下延伸,默認(rèn)為 0
3. 線型
可以通過一系列屬性來(lái)設(shè)置線的樣式置谦。
lineWidth = value; //設(shè)置或返回當(dāng)前的線條寬度堂鲤,默認(rèn)值是1.0,屬性值必須為正數(shù)
lineCap = butt | round | square; //設(shè)置或返回線條的結(jié)束端點(diǎn)樣式媒峡,默認(rèn)為butt
lineJoin = round | bevel | miter; //設(shè)置或返回兩條線接合處(相交時(shí)創(chuàng)建的拐角)的樣式瘟栖,默認(rèn)為miter
miterLimit = value; //設(shè)置或返回最大斜接長(zhǎng)度,斜接長(zhǎng)度(交接處長(zhǎng)度)是指線條交接處內(nèi)角頂點(diǎn)到外角頂點(diǎn)的長(zhǎng)度
getLineDash(); //返回一個(gè)包含當(dāng)前虛線樣式谅阿,長(zhǎng)度為非負(fù)偶數(shù)的數(shù)組
setLineDash(segments); //設(shè)置當(dāng)前虛線樣式
lineDashOffset = value; //設(shè)置虛線樣式的起始偏移量
詳解:
lineWidth:線寬是指給定路徑的中心到兩邊的粗細(xì)半哟。換句話說(shuō)就是在路徑的兩邊各繪制線寬的一半。因?yàn)楫嫴嫉淖鴺?biāo)并不和像素直接對(duì)應(yīng)签餐,當(dāng)需要獲得精確的水平或垂直線的時(shí)候要特別注意寓涨。
lineCap:butt表示線段端點(diǎn)在自己的格子內(nèi);round表示端點(diǎn)處加上了半徑為一半線寬的半圓氯檐; square 表示端點(diǎn)處加上了等寬且高度為一半線寬的方塊戒良。
lineJoin:round表示創(chuàng)建圓角,邊角處磨圓冠摄,圓的半徑等于線寬糯崎;bevel表示創(chuàng)建斜角几缭,一個(gè)線段內(nèi)邊與另一個(gè)線段外邊產(chǎn)生交點(diǎn),兩個(gè)交點(diǎn)相連沃呢,去掉外部尖角部分年栓,保留內(nèi)夾角部分;miter表示創(chuàng)建尖角薄霜,線段會(huì)在連接處外側(cè)延伸直至交于一點(diǎn)柠座,延伸效果受到miterLimit 屬性的制約艾帐。
miterLimit:miter效果時(shí)姿锭,線段的外側(cè)邊緣會(huì)延伸交匯于一點(diǎn)上茸炒。線段直接夾角比較大的,交點(diǎn)不會(huì)太遠(yuǎn)崎坊,但當(dāng)夾角減少時(shí)副编,交點(diǎn)距離會(huì)呈指數(shù)級(jí)增大。miterLimit 屬性就是用來(lái)設(shè)定外延交點(diǎn)與連接點(diǎn)的最大距離流强,如果交點(diǎn)距離大于此值痹届,連接效果會(huì)變成了 bevel。
4. 顏色
canvas有兩種上色:圖形填充fillStyle 和圖形輪廓strokeStyle 打月。
fillStyle = color | gradient | pattern; //css顏色值 | 漸變(線性或放射性)| 可重復(fù)的圖片
strokeStyle = color | gradient | pattern; //css顏色值 | 漸變(線性或放射性)| 可重復(fù)的圖片
其中:
默認(rèn)值是 #000000队腐。
color 詳解:
gradient 詳解:
gradient = cd.createLinearGradient(x1, y1, x2, y2); //創(chuàng)建漸變奏篙,從漸變的起點(diǎn) (x1,y1) 到漸變的終點(diǎn) (x2,y2)柴淘。
gradient = cd.createRadialGradient(x1, y1, r1, x2, y2, r2); //創(chuàng)建漸變秘通,從以 (x1,y1) 為原點(diǎn)为严,半徑為 r1 的圓,到另一個(gè)以 (x2,y2) 為原點(diǎn)肺稀,半徑為 r2 的圓第股。
創(chuàng)建出 canvasGradient 對(duì)象后,用 addColorStop 方法上色话原。
gradient.addColorStop(position, color); //position 參數(shù)必須是一個(gè) 0.0 與 1.0 之間的數(shù)值夕吻,表示漸變中顏色所在的相對(duì)位置。color 參數(shù)必須是一個(gè)有效的 CSS 顏色值繁仁。給同一位置設(shè)置兩種顏色涉馅,可以實(shí)現(xiàn)突變的效果。
示例:
var lingrad = cd.createLinearGradient(0,0,0,150); //新建一個(gè)漸變
lingrad.addColorStop(0, 'red'); //設(shè)置漸變起點(diǎn)為紅色
lingrad.addColorStop(0.5, 'blue'); //設(shè)置漸變中間點(diǎn)為藍(lán)色
lingrad.addColorStop(0.5, '#fff'); //設(shè)置漸變中間點(diǎn)突變?yōu)榘咨?lingrad.addColorStop(1, '#000'); //設(shè)置漸變結(jié)束點(diǎn)為黑色
cd.fillStyle = lingrad; //設(shè)置填充樣式為創(chuàng)建的漸變
cd.fillRect(0,0,100,100); //創(chuàng)建并填充矩形黄虱,矩形長(zhǎng)寬各100稚矿,從上往下,頂點(diǎn)到75%處為紅色變藍(lán)色,75%處到底部為白色變黑色
cd.fillRect(0,0,150,150); //創(chuàng)建并填充矩形晤揣,矩形長(zhǎng)寬各150偶翅,從上往下,頂點(diǎn)到中間為紅色變藍(lán)色碉渡,中間到底部為白色變黑色
pattern 詳解:
pattern = cd.createPattern(image, type); //image 可以是一個(gè) Image 對(duì)象的引用,或者另一個(gè) canvas 對(duì)象母剥。type 必須是下面的字符串值之一:repeat滞诺,repeat-x,repeat-y 和 no-repeat环疼。
注意:
用 canvas 對(duì)象作為 image 參數(shù)在 Firefox 1.5 (Gecko 1.8) 中是無(wú)效的习霹。
圖案的應(yīng)用跟漸變很類似的,創(chuàng)建出一個(gè)pattern之后炫隶,賦給 fillStyle 或 strokeStyle 屬性即可淋叶。
示例:
var img = new Image(); //新建一個(gè)Image對(duì)象
img.src = 'someimage.png'; //設(shè)置Image對(duì)象的實(shí)際引用圖片地址
var pattern = cd.createPattern(img,'repeat'); //創(chuàng)建pattern
cd.fillStyle = pattern; //賦值給fillStyle屬性
cd.fillRect(0,0,100,100); //將圖片填充矩形框
注意:
與drawImage不同,這里需要確認(rèn)Image對(duì)象已經(jīng)裝載完畢伪阶,否則圖案可能效果不對(duì)的煞檩。
5. 透明度
通過設(shè)置 globalAlpha 屬性或者使用一個(gè)半透明顏色作為輪廓或填充的樣式。
globalAlpha = value; //這個(gè)屬性影響到 canvas 里所有圖形的透明度栅贴,取值范圍在 0.0(完全透明)和 1.0(完全不透明)之間斟湃。 默認(rèn)值是1.0。 如果數(shù)值不在范圍內(nèi)檐薯,包括Infinity和NaN凝赛,無(wú)法賦值,并且globalAlpha會(huì)保持原有的數(shù)值坛缕。
注明:
少量顏色填充可以直接用rgba墓猎,不需要設(shè)置這個(gè)屬性
6. 填充規(guī)則
當(dāng)用到 fill(或者 clip和isPointinPath )時(shí),可以選擇一個(gè)填充規(guī)則赚楚,該填充規(guī)則根據(jù)某處在路徑的外面或者里面來(lái)決定該處是否被填充毙沾,這對(duì)于自己與自己路徑相交或者路徑被嵌套的時(shí)候是有用的。
cd.fill(); //使用默認(rèn)值直接填充
cd.fill("nonzero"); //非零環(huán)繞原則宠页,是默認(rèn)值
cd.fill("evenodd"); //奇偶原則
兩個(gè)原則詳解
非零環(huán)繞原則nonzero詳解:
用來(lái)判斷哪些區(qū)域?qū)儆诼窂絻?nèi)( 計(jì)算結(jié)果非0搀军,即為路徑內(nèi) )。
* 在路徑包圍的區(qū)域中勇皇,隨便找一點(diǎn)罩句,向外發(fā)射一條射線,
* 和所有圍繞它的邊相交敛摘,
* 然后開啟一個(gè)計(jì)數(shù)器门烂,從0計(jì)數(shù),
* 如果這個(gè)射線遇到順時(shí)針圍繞,那么+1屯远,
* 如果遇到逆時(shí)針圍繞蔓姚,那么-1,
* 如果最終值非0慨丐,則這塊區(qū)域在路徑內(nèi)坡脐。
奇偶原則evenodd詳解:
* 在路徑包圍的區(qū)域中,隨便找一點(diǎn)房揭,向外發(fā)射一條射線备闲,
* 和所有圍繞它的邊相交,
* 查看相交線的個(gè)數(shù)捅暴,如果為奇數(shù)恬砂,就填充,如果是偶數(shù)蓬痒,就不填充泻骤。
繪制
1. 繪制矩形
canvas只支持一種原生的圖形繪制:矩形。所有其他的圖形的繪制都至少需要生成一條路徑梧奢。
矩形的繪制有三種方法:
fillRect( x , y , width , height ) //繪制一個(gè)填充的矩形
strokeRect( x , y , width , height ) //繪制一個(gè)矩形的邊框
clearRect( x , y , width , height ) //清空指定的矩形區(qū)域狱掂,讓去除部分完全透明
其中:
(x,y)起點(diǎn) width寬 height高
2. 繪制路徑
路徑是通過不同顏色和寬度的線段或曲線相連接形成的不同形狀的點(diǎn)的集合。
圖形的基本元素是路徑亲轨。一個(gè)路徑符欠,甚至一個(gè)子路徑,都是閉合的瓶埋。
使用路徑繪制圖形的步驟:
①創(chuàng)建路徑起始點(diǎn)希柿;
②使用畫圖命令去畫出路徑;
③把路徑封閉养筒;
④路徑生成后曾撤,通過描邊或填充路徑區(qū)域來(lái)渲染圖形。
使用路徑繪制圖形的函數(shù):
beginPath() //新建一條路徑晕粪,生成之后挤悉,圖形繪制命令被指向到路徑上生成路徑
closePath() //閉合路徑之后圖形繪制指令又重新指向到上下文中
stroke() //通過線條來(lái)繪制圖形輪廓,不會(huì)自動(dòng)閉合沒有閉合的形狀
fill() //通過填充路徑的內(nèi)容區(qū)域生成實(shí)心的圖形巫湘,自動(dòng)閉合所有沒有閉合的形狀装悲,不需要調(diào)用closePath()函數(shù)
moveTo( x , y ) //移動(dòng)筆觸,將筆觸移動(dòng)到指定的坐標(biāo)(x , y)上
lineTo( x , y ) //繪制一條從當(dāng)前位置到指定的位置(x , y)的直線
弧線
arc( x , y , radius , startAngle , endAngle , anticlockwise) //畫一個(gè)以(x , y)為圓心尚氛,以radius為半徑的圓痪髡铩(圓),從startAngle 開始到endAngle 結(jié)束阅嘶,anticlockwise參數(shù)為一個(gè)布爾值属瓣,true表示逆時(shí)針载迄,false表示順時(shí)針。
注意:
arc()函數(shù)中的角度單位是弧度抡蛙,不是度數(shù)护昧。角度與弧度的js表達(dá)式:弧度= 角度 * Math.PI / 180,角度 = 弧度 * 180 / Math.PI
貝塞爾(bezier)以及二次貝塞爾
quadraticCurveTo( cp1x , cp1y , x , y ) //繪制二次貝塞爾曲線粗截,(x , y)為結(jié)束點(diǎn)惋耙,(cp1x , cp1y)為控制點(diǎn)
bezierCurveTo( cp1x , cp1y , cp2x , cp2y , x , y ) //繪制三次貝塞爾曲線,(x , y)為結(jié)束點(diǎn)熊昌,(cp1x , cp1y)為控制點(diǎn)一 绽榛,(cp2x , cp2y)為控制點(diǎn)二
矩形
rect( x , y , width , height ) //繪制一個(gè)左上角坐標(biāo)為(x , y),寬為width高為height的矩形
Path2D對(duì)象(詳情)
new Path2D() //空的Path對(duì)象
new Path2D(path) //克隆Path對(duì)象
new Path2D(d) //從SVG建立Path對(duì)象
說(shuō)明:
Path2D對(duì)象用來(lái)緩存或記錄繪畫命令浴捆,用以快速回顧路徑
例子:
var path = new Path2D();
path.rect(50,50,50,50);
cd.stroke(path);
3. 繪制文本
屬性設(shè)置:
font = value //設(shè)置或返回文本內(nèi)容的當(dāng)前字體屬性。 使用和 CSS font 屬性相同的語(yǔ)法稿械,默認(rèn)的字體是 10px sans-serif选泻。
textAlign = value // 設(shè)置或返回文本內(nèi)容的當(dāng)前對(duì)齊方式∶滥可選的值包括:start, end, left, right or center页眯。 默認(rèn)值是 start。
textBaseline = value //設(shè)置或返回在繪制文本時(shí)使用的當(dāng)前文本基線厢呵。 可選的值包括:top, hanging, middle, alphabetic, ideographic, bottom窝撵。默認(rèn)值是 alphabetic。
direction = value //文本方向襟铭÷捣睿可能的值包括:ltr, rtl, inherit。默認(rèn)值是 inherit寒砖。
渲染文本:
fillText(text, x, y [, maxWidth]) //在指定的(x,y)位置填充指定的文本赐劣,繪制的最大寬度是可選的。
strokeText(text, x, y [, maxWidth]) //在指定的(x,y)位置繪制文本邊框哩都,繪制的最大寬度是可選的魁兼。
測(cè)量文本:
measureText() //返回包含指定文本寬度的TextMetrics對(duì)象,詳解見備注漠嵌。
注:
measureText()使用
TextMetrics對(duì)象詳解
4. 繪制圖像
canvas可以用于動(dòng)態(tài)的圖像合成或者作為圖形的背景咐汞。瀏覽器支持的任意格式的外部圖片都可以使用,比如PNG儒鹿、GIF或者JPEG化撕,也可以將同一個(gè)頁(yè)面中其他canvas元素生成的圖片作為圖片源。
引入圖像到canvas的基本操作:
獲得一個(gè)指向HTMLImageElement的對(duì)象或者另一個(gè)canvas元素的引用作為源约炎,也可以通過提供一個(gè)URL的方式來(lái)使用圖片侯谁,使用drawImage()函數(shù)將圖片繪制到畫布上。
canvas的API可以使用下面這些類型中的一種作為圖片的源:
HTMLImageElement //由Image()函數(shù)構(gòu)造出來(lái)的圖片,或者任何的<img>元素
HTMLVideoElement //用一個(gè)HTML的 <video>元素作為圖片源墙贱,可以從視頻中抓取當(dāng)前幀作為一個(gè)圖像
HTMLCanvasElement //用另一個(gè) <canvas> 元素作為圖片源热芹。
ImageBitmap //一個(gè)高性能的位圖,可以低延遲地繪制惨撇,它可以從上述的所有源以及其它幾種源中生成伊脓。
注:這些源統(tǒng)一由 CanvasImageSource類型來(lái)引用。
①使用相同頁(yè)面內(nèi)的圖片
通過下列方法的一種來(lái)獲得與canvas相同頁(yè)面內(nèi)的圖片的引用:
document.images集合
document.getElementsByTagName()方法
document.getElementById()獲得指定圖片
②使用其它域名下的圖片
在 HTMLImageElement上使用crossOrigin屬性魁衙,可以請(qǐng)求加載其它域名上的圖片报腔。如果圖片的服務(wù)器允許跨域訪問這個(gè)圖片,那么你可以使用這個(gè)圖片而不污染canvas剖淀,否則纯蛾,使用這個(gè)圖片將會(huì)污染canvas。
注:污染canvas詳解
③使用其它 canvas 元素
和引用頁(yè)面內(nèi)的圖片類似地纵隔,用 document.getElementsByTagName 或 document.getElementById 方法來(lái)獲取其它 canvas 元素翻诉。但你引入的應(yīng)該是已經(jīng)準(zhǔn)備好的 canvas。
④由零開始創(chuàng)建圖像
用腳本創(chuàng)建一個(gè)新的 HTMLImageElement 對(duì)象捌刮。使用Image()構(gòu)造函數(shù)碰煌。
var img = new Image(); // 創(chuàng)建一個(gè)<img>元素
img.src = 'myImage.png'; // 設(shè)置圖片源地址
當(dāng)腳本執(zhí)行后,圖片開始裝載绅作。
若調(diào)用 drawImage 時(shí)芦圾,圖片沒裝載完,那什么都不會(huì)發(fā)生(在一些舊的瀏覽器中可能會(huì)拋出異常)俄认。因此應(yīng)該用load事件來(lái)保證不會(huì)在加載完畢之前使用這個(gè)圖片:
var img = new Image(); // 創(chuàng)建img元素
img.onload = function(){
// 執(zhí)行drawImage語(yǔ)句
}
img.src = 'myImage.png'; // 設(shè)置圖片源地址
注:如果只用到一張圖片个少,如上操作。如果需要不止一張圖片眯杏,則應(yīng)使用圖片預(yù)加載策略稍算。
⑤通過 data: url 方式嵌入圖像
可以通過 data:url 方式來(lái)引用圖像。Data urls 允許用一串 Base64 編碼的字符串的方式來(lái)定義一個(gè)圖片役拴。
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
優(yōu)點(diǎn)是圖片內(nèi)容即時(shí)可用糊探,無(wú)須再到服務(wù)器兜一圈,可以將 CSS河闰、JavaScript科平、HTML 和 圖片全部封裝在一起,遷移方便姜性。
缺點(diǎn)就是圖像沒法緩存瞪慧,圖片較大時(shí),內(nèi)嵌的 url 數(shù)據(jù)會(huì)相當(dāng)長(zhǎng):
⑥使用視頻幀
可以使用<video> 中的視頻幀(即便視頻是不可見的)部念。HTMLVideoElement對(duì)象可以作為canvas圖片源弃酌。
獲得源圖對(duì)象后氨菇,可以使用 drawImage 方法將它渲染到 canvas 里。drawImage 方法有下面三種形態(tài):
drawImage(image, x, y) //其中image 是 image 或者 canvas 對(duì)象妓湘,x 和 y 是其在目標(biāo) canvas 里的起始坐標(biāo)查蓉。SVG圖像必須在 <svg> 根指定元素的寬度和高度。
drawImage(image, x, y, width, height) //這個(gè)方法多了2個(gè)參數(shù):width 和 height榜贴,這兩個(gè)參數(shù)用來(lái)控制 當(dāng)向canvas畫入時(shí)應(yīng)該縮放的大小
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) //第一個(gè)參數(shù)和其它的是相同的豌研,都是一個(gè)圖像或者另一個(gè) canvas 的引用。其它8個(gè)參數(shù)唬党,前4個(gè)是定義圖像源的切片位置和大小鹃共,后4個(gè)則是定義切片的目標(biāo)顯示位置和大小。