Canvas繪圖
- HTML5 的 canvas 元素使用 JavaScript 在網(wǎng)頁上繪制圖像。
- 畫布是一個(gè)矩形區(qū)域,您可以控制其每一像素。
- canvas 擁有多種繪制路徑、矩形、圓形、字符以及添加圖像的方法。
- 瀏覽器支持
- Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支持
<canvas>及其屬性和方法。 - 注釋:Internet Explorer 8 以及更早的版本不支持
<canvas>元素。
- Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支持
- HTML 5 Canvas 參考手冊
1、基本用法
(1)創(chuàng)建 Canvas 元素
- 向 HTML5 頁面添加 canvas 元素。
- 規(guī)定元素的 id、寬度和高度。
- 開始和結(jié)束標(biāo)簽中的內(nèi)容是后備信息,如果瀏覽器不支持
<canvas>元素,就會(huì)顯示這些信息。
<canvas id = "drawing" width = "200" height= "200">A drawing of something</canvas>
(2)通過 JavaScript 來繪制
- canvas 元素本身是沒有繪圖能力的。所有的繪制工作必須在 JavaScript 內(nèi)部完成。
- 要在這塊畫布(canvas)上繪圖,需要取得繪圖上下文。而取得繪圖上下文對象的引用,需要調(diào)用getContext()方法并傳入上下文的名字。
var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
//更多代碼
}
- 使用toDataURL()方法,可以導(dǎo)出在
<canvas>元素上繪制的圖像。這個(gè)方法接受一個(gè)參數(shù),即圖像的MIME 類型格式,而且適合用于創(chuàng)建圖像的任何上下文。
var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
//取得圖像的數(shù)據(jù)URI
var imgURI = drawing.toDataURL("image/png");
//顯示圖像
var image = document.createElement("img");
image.src = imgURI;
document.body.appendChild(image);
}
2、2D上下文
- 使用2D 繪圖上下文提供的方法,可以繪制簡單的2D 圖形,比如矩形、弧線和路徑。
- 2D 上下文的坐標(biāo)開始于
<canvas>元素的左上角,原點(diǎn)坐標(biāo)是(0,0)。所有坐標(biāo)值都基于這個(gè)原點(diǎn)計(jì)算,x 值越大表示越靠右,y 值越大表示越靠下。 - 默認(rèn)情況下,width 和height 表示水平和垂直兩個(gè)方向上可用的像素?cái)?shù)目。
2.1 填充和描邊
- 填充,就是用指定的樣式(顏色、漸變或圖像)填充圖形;
- 描邊,就是只在圖形的邊緣畫線。
| 屬性 | 描述 |
|---|---|
| fillStyle | 設(shè)置或返回用于填充繪畫的顏色、漸變或模式 |
| strokeStyle | 設(shè)置或返回用于筆觸的顏色、漸變或模式 |
- 這兩個(gè)屬性的值可以是字符串、漸變對象或模式對象,而且它們的默認(rèn)值都是"#000000"。
- 如果為它們指定表示顏色的字符串值,可以使用CSS中指定顏色值的任何格式,包括顏色名、十六進(jìn)制碼、rgb、rgba、hsl 或hsla。
var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
var context = drawing.getContext("2d");
context.strokeStyle = "red";
context.fillStyle = "#0000ff";
}
2.2 繪制矩形
- 矩形是唯一一種可以直接在2D上下文中繪制的形狀。
- 與矩形有關(guān)的有四個(gè)方法。
| 方法 | 描述 |
|---|---|
| rect() | 創(chuàng)建矩形 |
| fillRect() | 繪制“被填充”的矩形 |
| strokeRect() | 繪制矩形(無填充) |
| clearRect() | 在給定的矩形內(nèi)清除指定的像素 |
- 這幾個(gè)方法都能接收4個(gè)參數(shù)
| 參數(shù) | 描述 |
|---|---|
| x | 矩形左上角的 x 坐標(biāo) |
| y | 矩形左上角的 y 坐標(biāo) |
| width | 矩形的寬度,以像素計(jì) |
| height | 矩形的高度,以像素計(jì) |
<!--示例畫布-->
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
(1) rect()
- 使用 stroke() 或 fill() 方法在畫布上實(shí)際地繪制矩形。
- javascript 語法
context.rect(x,y,width,height);
- 示例
/**通過 rect() 方法來創(chuàng)建三個(gè)矩形**/
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// 紅色矩形
ctx.beginPath();
ctx.lineWidth="6";
ctx.strokeStyle="red";
ctx.rect(5,5,290,140);
ctx.stroke();
// 綠色矩形
ctx.beginPath();
ctx.lineWidth="4";
ctx.strokeStyle="green";
ctx.rect(30,30,50,50);
ctx.stroke();
// 藍(lán)色矩形
ctx.beginPath();
ctx.lineWidth="10";
ctx.strokeStyle="blue";
ctx.rect(50,50,150,80);
ctx.stroke();

(2)fillRect()
- fillRect()方法在畫布上繪制的矩形會(huì)填充指定的顏色。填充的顏色通過fillStyle 屬
性指定。 - javascript 語法
context.fillRect(x,y,width,height);
- 示例
/**繪制填充矩形**/
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
//繪制紅色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//繪制半透明的藍(lán)色矩形
context.fillStyle = "rgba(0,0,255,0.5)";
context.fillRect(30, 30, 50, 50);

(3)strokeRect()
- strokeRect() 方法繪制矩形(不填色)。筆觸的默認(rèn)顏色是黑色。
- strokeRect()方法在畫布上繪制的矩形會(huì)使用指定的顏色描邊。描邊顏色通過strokeStyle 屬性指定。
- javascript 語法
context.strokeRect(x,y,width,height);
- 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
//繪制紅色描邊矩形
context.strokeStyle = "#ff0000";
context.strokeRect(10, 10, 50, 50);
//繪制半透明的藍(lán)色描邊矩形
context.strokeStyle = "rgba(0,0,255,0.5)";
context.strokeRect(30, 30, 50, 50);

(4)clearRect()
- clearRect()方法用于清除畫布上的矩形區(qū)域。
- 本質(zhì)上,這個(gè)方法可以把繪制上下文中的某一矩形區(qū)域變透明。通過繪制形狀然后再清除指定區(qū)域,就可以生成有意思的效果。
- javascript 語法
context.clearRect(x,y,width,height);
- 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
//繪制紅色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//繪制半透明的藍(lán)色矩形
context.fillStyle = "rgba(0,0,255,0.5)";
context.fillRect(30, 30, 50, 50);
//在兩個(gè)矩形重疊的地方清除一個(gè)小矩形
context.clearRect(40, 40, 10, 10);

2.3 繪制路徑
- 2D 繪制上下文支持很多在畫布上繪制路徑的方法。通過路徑可以創(chuàng)造出復(fù)雜的形狀和線條。
| 方法 | 描述 |
|---|---|
| fill() | 填充當(dāng)前繪圖(路徑) |
| stroke() | 繪制已定義的路徑 |
| beginPath() | 起始一條路徑,或重置當(dāng)前路徑 |
| moveTo() | 把路徑移動(dòng)到畫布中的指定點(diǎn),不創(chuàng)建線條 |
| closePath() | 創(chuàng)建從當(dāng)前點(diǎn)回到起始點(diǎn)的路徑 |
| lineTo() | 添加一個(gè)新點(diǎn),然后在畫布中創(chuàng)建從該點(diǎn)到最后指定點(diǎn)的線條 |
| clip() | 從原始畫布剪切任意形狀和尺寸的區(qū)域 |
| quadraticCurveTo() | 創(chuàng)建二次貝塞爾曲線 |
| bezierCurveTo() | 創(chuàng)建三次方貝塞爾曲線 |
| arc() | 創(chuàng)建弧/曲線(用于創(chuàng)建圓形或部分圓) |
| arcTo() | 創(chuàng)建兩切線之間的弧/曲線 |
| isPointInPath() | 如果指定的點(diǎn)位于當(dāng)前路徑中,則返回 true,否則返回 false |
(1)fill()
- fill() 方法填充當(dāng)前的圖像(路徑)。默認(rèn)顏色是黑色。
- 使用 fillStyle 屬性來填充另一種顏色/漸變。
- javascript 語法
context.fill();
- 示例
var c=document.getElementById("myCanvas");
var context = c.getContext('2d');
context.rect(20,20,150,100)
context.fillStyle = "green";
context.fill();

(2)stroke()
- stroke() 方法會(huì)實(shí)際地繪制出通過moveTo()和lineTo()方法定義的路徑。默認(rèn)顏色是黑色。
- 使用 strokeStyle 屬性來繪制另一種顏色/漸變。
- javascript 語法
context.stroke();
- 示例
var c=document.getElementById("myCanvas");
var context = c.getContext('2d');
context.beginPath();
context.moveTo(20,20);
context.lineTo(20,100);
context.lineTo(70,100);
context.strokeStyle = "green";
context.stroke();

(3)beginPath()、moveTo()、lineTo()
- beginPath() 方法開始一條路徑,或重置當(dāng)前的路徑。
- moveTo(x, y):將繪圖游標(biāo)移動(dòng)到(x,y),不畫線。
- lineTo(x, y):從上一點(diǎn)開始繪制一條直線,到(x,y)為止。
- javascript 語法
context.beginPath();
context.moveTo(x,y);
context.lineTo(x,y);
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.strokeStyle="red"; // 綠色路徑
ctx.moveTo(0,75);
ctx.lineTo(300,75);
ctx.stroke(); // 進(jìn)行繪制
ctx.beginPath();
ctx.strokeStyle="blue"; // 紫色路徑
ctx.moveTo(150,0);
ctx.lineTo(150,150);
ctx.stroke(); // 進(jìn)行繪制

(4)closePath()
closePath() 方法創(chuàng)建從當(dāng)前點(diǎn)到開始點(diǎn)的路徑。
使用 stroke() 方法在畫布上繪制確切的路徑。
使用 fill() 方法來填充圖像(默認(rèn)是黑色)。請使用fillStyle屬性來填充另一個(gè)顏色/漸變。
javascript 語法
context.closePath();
- 示例
var c = document.getElementById("myCanvas");
var context = c.getContext('2d');
context.beginPath();
context.moveTo(20,20);
context.lineTo(20,100);
context.lineTo(100,100);
context.closePath();
context.stroke();
context.fillStyle = "green";
context.fill();

(5)clip()
- clip() 方法從原始畫布中剪切任意形狀和尺寸。
- javascript語法
context.clip();
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// Draw a rectangle
ctx.rect(50,20,200,120);
ctx.stroke();
// Draw green rectangle
ctx.fillStyle="green";
ctx.fillRect(0,0,150,100);
var c=document.getElementById("myCanvas2");
var ctx=c.getContext("2d");
// Clip a rectangular area
ctx.rect(50,20,200,120);
ctx.stroke();
ctx.clip();
// Draw red rectangle after clip()
ctx.fillStyle="red";
ctx.fillRect(0,0,150,100);

(6)quadraticCurveTo()
quadraticCurveTo() 方法通過使用表示二次貝塞爾曲線的指定控制點(diǎn),向當(dāng)前路徑添加一個(gè)點(diǎn)。
javascript 語法
context.quadraticCurveTo(cpx,cpy,x,y);
從上一點(diǎn)開始繪制一條二次曲線,到(x,y)為止,并且以(cpx,cpy)作為控制點(diǎn)。
示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.quadraticCurveTo(20,100,200,20);
ctx.stroke();

- 二次貝塞爾曲線需要兩個(gè)點(diǎn)。第一個(gè)點(diǎn)是用于二次貝塞爾計(jì)算中的控制點(diǎn),第二個(gè)點(diǎn)是曲線的結(jié)束點(diǎn)。
-
曲線的開始點(diǎn)是當(dāng)前路徑中最后一個(gè)點(diǎn)。如果路徑不存在,那么請使用 beginPath() 和 moveTo() 方法來定義開始點(diǎn)。
quadraticCurveTo分析.png
(7)bezierCurveTo()
- bezierCurveTo() 方法通過使用表示三次貝塞爾曲線的指定控制點(diǎn),向當(dāng)前路徑添加一個(gè)點(diǎn)。
- javascript 語法
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
從上一點(diǎn)開始繪制一條曲線,到(x,y)為止,并且以(cp1x,cp1y)和(cp2x,cp2y)為控制點(diǎn)。
示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.bezierCurveTo(20,100,200,100,200,20);
ctx.stroke();

- 三次貝塞爾曲線需要三個(gè)點(diǎn)。前兩個(gè)點(diǎn)是用于三次貝塞爾計(jì)算中的控制點(diǎn),第三個(gè)點(diǎn)是曲線的結(jié)束點(diǎn)。
-
曲線的開始點(diǎn)是當(dāng)前路徑中最后一個(gè)點(diǎn)。如果路徑不存在,那么請使用 beginPath() 和 moveTo() 方法來定義開始點(diǎn)。
bezierCurveTo分析
(8)arc()
- arc() 方法創(chuàng)建弧/曲線(用于創(chuàng)建圓或部分圓)。
- javascript 語法
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
- 參數(shù)值
| 參數(shù) | 描述 |
|---|---|
| x | 圓的中心的 x 坐標(biāo)。 |
| y | 圓的中心的 y 坐標(biāo)。 |
| r | 圓的半徑。 |
| sAngle | 起始角,以弧度計(jì)。(弧的圓形的三點(diǎn)鐘位置是 0 度)。 |
| eAngle | 結(jié)束角,以弧度計(jì)。 |
| counterclockwise | 可選。規(guī)定應(yīng)該逆時(shí)針還是順時(shí)針繪圖。False = 順時(shí)針,true = 逆時(shí)針。 |
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.arc(100,75,50,0,2*Math.PI);
ctx.stroke();

- 如需通過 arc() 來創(chuàng)建圓,請把起始角設(shè)置為 0,結(jié)束角設(shè)置為 2*Math.PI。
-
使用 stroke() 或 fill() 方法在畫布上繪制實(shí)際的弧。
arc()角度.png
(9)arcTo()
- arcTo() 方法在畫布上創(chuàng)建介于兩個(gè)切線之間的弧/曲線。
- 從上一點(diǎn)開始繪制一條弧線,到(x2,y2)為止,并且以給定的半徑radius 穿過(x1,y1)。
- javascript 語法
context.arcTo(x1, y1, x2, y2, radius)
- 示例
//獲取Canvas對象(畫布)
var canvas = document.getElementById("myCanvas");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
ctx.moveTo(50, 50);
//端點(diǎn)1
var p1 = {
x : 200,
y : 50
};
//端點(diǎn)2
var p2 = {
x : 200,
y : 100
};
//繪制與當(dāng)前端點(diǎn)、端點(diǎn)1、端點(diǎn)2三個(gè)點(diǎn)所形成的夾角的兩邊相切并且半徑為50px的圓的一段弧線
ctx.arcTo(p1.x, p1.y, p2.x, p2.y, 50);
ctx.strokeStyle = "blue";
ctx.stroke();
}

(10)isPointInPath()
- isPointInPath() 方法返回 true,如果指定的點(diǎn)位于當(dāng)前路徑中;否則返回 false。
- javascrit 語法
context.isPointInPath(x,y);
- 示例
var c=document.getElementById("myCanvas");
var context = c.getContext("2d");
context.rect(10,10,100,100);
if(context.isPointInPath(20,50)){
context.stroke();
}

2.4 繪制文本
- 2D 繪圖上下文提供了2個(gè)繪制文本方法和一個(gè)相關(guān)方法
- fillText()和strokeText()都可以接收4個(gè)參數(shù):要繪制的文本字符串、x坐標(biāo)、y坐標(biāo)和可選的最大像素寬度。而measureText()接受一個(gè)參數(shù),表示要測量的文本。
| 方法 | 描述 |
|---|---|
| fillText() | 在畫布上繪制“被填充的”文本 |
| strokeText() | 在畫布上繪制文本(無填充) |
| measureText() | 返回包含指定文本寬度的對象 |
- 這兩個(gè)方法都以下列3 個(gè)屬性為基礎(chǔ)。
| 屬性 | 描述 |
|---|---|
| font | 設(shè)置或返回文本內(nèi)容的當(dāng)前字體屬性 |
| textAlign | 設(shè)置或返回文本內(nèi)容的當(dāng)前對齊方式,建議使用"start"和"end" |
| textBaseline | 表示文本的基線,可以調(diào)整文本的垂直對齊方式 |
(1)fillText()
- fillText() 方法在畫布上繪制填色的文本。文本的默認(rèn)顏色是黑色。
- javascript 語法
context.fillText(text,x,y,maxWidth);
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="30px Times new Roman";
ctx.fillStyle = "red"
ctx.fillText("Hello World!",10,50);

(2)strokeText()
- strokeText() 方法在畫布上繪制文本(沒有填色)。文本的默認(rèn)顏色是黑色。
- javascript 語法
context.strokeText(text,x,y,maxWidth);
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="40px Times new Roman";
ctx.strokeStyle = "red";
ctx.strokeText("Hello World!",10,50);

(3)measureText()
- measureText() 方法返回包含一個(gè)對象,該對象包含以像素計(jì)的指定字體寬度。
- javascript 語法
context.measureText(text).width;
- 示例
//在畫布上輸出文本之前,檢查字體的寬度
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="20px Arial";
var txt="Hello World"
ctx.fillText("width:" + ctx.measureText(txt).width,10,50);
ctx.fillText(txt,10,100);

(4)textAlign
- textAlign 屬性根據(jù)錨點(diǎn),設(shè)置或返回文本內(nèi)容的當(dāng)前對齊方式。
- javascript 語法
context.textAlign="center|end|left|right|start";
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// Create a red line in position 150
ctx.strokeStyle="blue";
ctx.moveTo(150,20);
ctx.lineTo(150,170);
ctx.stroke();
ctx.font="15px Arial";
// Show the different textAlign values
ctx.textAlign="start";
ctx.fillText("textAlign=start",150,60);
ctx.textAlign="end";
ctx.fillText("textAlign=end",150,80);
ctx.textAlign="left";
ctx.fillText("textAlign=left",150,100);
ctx.textAlign="center";
ctx.fillText("textAlign=center",150,120);
ctx.textAlign="right";
ctx.fillText("textAlign=right",150,140);

(5)textBaseline
- textBaseline 屬性設(shè)置或返回在繪制文本時(shí)的當(dāng)前文本基線。
- javascript 語法
context.textBaseline="alphabetic|top|hanging|middle|ideographic|bottom";
- 示例

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
//Draw a red line at y=100
ctx.strokeStyle="blue";
ctx.moveTo(5,100);
ctx.lineTo(395,100);
ctx.stroke();
ctx.font="20px Arial"
//Place each word at y=100 with different textBaseline values
ctx.textBaseline="top";
ctx.fillText("Top",5,100);
ctx.textBaseline="bottom";
ctx.fillText("Bottom",50,100);
ctx.textBaseline="middle";
ctx.fillText("Middle",120,100);
ctx.textBaseline="alphabetic";
ctx.fillText("Alphabetic",190,100);
ctx.textBaseline="hanging";
ctx.fillText("Hanging",290,100);

2.5 變換
2D 繪制上下文支持各種基本的繪制變換。創(chuàng)建繪制上下文時(shí),會(huì)以默認(rèn)值初始化變換矩陣,在默認(rèn)的變換矩陣下,所有處理都按描述直接繪制。
為繪制上下文應(yīng)用變換,會(huì)導(dǎo)致使用不同的變換矩陣應(yīng)用處理,從而產(chǎn)生不同的結(jié)果。
可以通過如下方法來修改變換矩陣。
| 方法 | 描述 |
|---|---|
| scale() | 縮放當(dāng)前繪圖至更大或更小 |
| rotate() | 旋轉(zhuǎn)當(dāng)前繪圖 |
| translate() | 重新映射畫布上的 (0,0) 位置 |
| transform() | 替換繪圖的當(dāng)前轉(zhuǎn)換矩陣 |
| setTransform() | 將當(dāng)前轉(zhuǎn)換重置為單位矩陣。然后運(yùn)行 transform() |
(1)scale()
- scale() 方法縮放當(dāng)前繪圖,更大或更小。
- 如果您對繪圖進(jìn)行縮放,所有之后的繪圖也會(huì)被縮放。定位也會(huì)被縮放。
- javascript語法
context.scale(scalewidth,scaleheight);
- 縮放圖像,在x 方向乘以scaleX,在y 方向乘以scaleY。scaleX和scaleY 的默認(rèn)值都是1.0。
- 參數(shù)值
| 參數(shù) | 描述 |
|---|---|
| scalewidth | 縮放當(dāng)前繪圖的寬度 (1=100%, 0.5=50%, 2=200%, 依次類推) |
| scaleheight | 縮放當(dāng)前繪圖的高度 (1=100%, 0.5=50%, 2=200%, etc.) |
/**依次放大**/
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.strokeRect(5,5,25,15);
ctx.scale(2,2);
ctx.strokeRect(5,5,25,15);
ctx.scale(2,2);
ctx.strokeRect(5,5,25,15);
ctx.scale(2,2);
ctx.strokeRect(5,5,25,15);

(2)rotate()
- rotate(angle),圍繞原點(diǎn)旋轉(zhuǎn)圖像angle 弧度。
- javascript 語法
context.rotate(angle);
- 參數(shù)值
參數(shù)| 描述
-|-
angle |旋轉(zhuǎn)角度,以弧度計(jì)。如需將角度轉(zhuǎn)換為弧度,請使用degreesMath.PI/180 公式進(jìn)行計(jì)算。舉例:如需旋轉(zhuǎn) 5 度,可規(guī)定下面的公式:5Math.PI/180。
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rotate(20*Math.PI/180);
ctx.fillRect(50,20,100,50);

(3)translate()
- translate(x, y):將坐標(biāo)原點(diǎn)移動(dòng)到(x,y)。執(zhí)行這個(gè)變換之后,坐標(biāo)(0,0)會(huì)變成之前由(x,y)表示的點(diǎn)。
- javascript語法
context.translate(x,y);
- 示例
/**繪制一個(gè)簡易的時(shí)鐘**/
var c=document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(150,75,70,0,2*Math.PI);
ctx.stroke();
ctx.moveTo(215,75);
ctx.arc(150,75,65,0,2*Math.PI);
//變換原點(diǎn)
ctx.translate(150,75);
ctx.textBaseline = "middle";
ctx.fillText('3',50,0);
ctx.textAlign="center";
ctx.fillText('6',0,55);
ctx.fillText('9',-50,0);
ctx.fillText('12',0,-55);
ctx.moveTo(0,0);
ctx.lineTo(35,0);
ctx.moveTo(0,0);
ctx.lineTo(0,-50);
ctx.stroke();

(4)transform()
- 畫布上的每個(gè)對象都擁有一個(gè)當(dāng)前的變換矩陣。
- transform() 方法替換當(dāng)前的變換矩陣。它以下面描述的矩陣來操作當(dāng)前的變換矩陣
a c e
b d f
0 0 1
- transform() 允許您縮放、旋轉(zhuǎn)、移動(dòng)并傾斜當(dāng)前的環(huán)境。
- javascript語法
context.transform(a,b,c,d,e,f);
- 參數(shù)值
參數(shù)| 描述
-|-
a| 水平縮放繪圖
b| 水平傾斜繪圖
c| 垂直傾斜繪圖
d| 垂直縮放繪圖
e| 水平移動(dòng)繪圖
f| 垂直移動(dòng)繪圖
-
示例
矩陣公式 - 由此可見,transform(x, 0, 0, y, 0, 0),等同于scale(x,y); transform(1, 0, 0, 1, x, y),等同于translate(x,y);
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.strokeStyle="green";
ctx.strokeRect(0,0,100,30)
//等同于translate(x,y)
ctx.transform(1,0,0,1,30,30);
ctx.strokeStyle="red";
ctx.strokeRect(0,0,100,30);
//等同于scale(2,2)
ctx.transform(2,0,0,2,0,0);
ctx.strokeStyle="blue";
ctx.strokeRect(0,0,100,30);
//水平和豎直方向傾斜
ctx.transform(1,0.5,0.5,1,0,0);
ctx.strokeStyle="black";
ctx.strokeRect(0,0,100,30);

(5)setTransform()
- setTransform() 方法把當(dāng)前的變換矩陣重置為單位矩陣,然后以相同的參數(shù)運(yùn)行 transform()。
- javascript語法
context.setTransform(a,b,c,d,e,f);
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.strokeStyle="green";
ctx.strokeRect(0,0,100,30)
//等同于translate(x,y)
ctx.setTransform(1,0,0,1,30,30);
ctx.strokeStyle="red";
ctx.strokeRect(0,0,100,30);
//等同于scale(2,2)
ctx.setTransform(2,0,0,2,0,0);
ctx.strokeStyle="blue";
ctx.strokeRect(0,0,100,30);
//水平和豎直方向傾斜
ctx.setTransform(1,0.5,0.5,1,0,0);
ctx.strokeStyle="black";
ctx.strokeRect(0,0,100,30);

2.6 繪制圖像
- drawImage() 方法在畫布上繪制圖像、畫布或視頻。
- drawImage() 方法也能夠繪制圖像的某些部分,以及/或者增加或減少圖像的尺寸。
- JavaScript 語法
/***語法一,在畫布上定位圖像*/
context.drawImage(img,x,y);
/**語法二,在畫布上定位圖像,并規(guī)定圖像的寬度和高度**/
context.drawImage(img,x,y,width,height);
/**語法三,剪切圖像,并在畫布上定位被剪切的部分**/
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
- 參數(shù)值
| 參數(shù) | 描述 |
|---|---|
| img | 規(guī)定要使用的圖像、畫布或視頻。 |
| sx | 可選。開始剪切的 x 坐標(biāo)位置。 |
| sy | 可選。開始剪切的 y 坐標(biāo)位置。 |
| swidth | 可選。被剪切圖像的寬度。 |
| sheight | 可選。被剪切圖像的高度。 |
| x | 在畫布上放置圖像的 x 坐標(biāo)位置。 |
| y | 在畫布上放置圖像的 y 坐標(biāo)位置。 |
| width | 可選。要使用的圖像的寬度。(伸展或縮小圖像) |
height 可選。要使用的圖像的高度。(伸展或縮小圖像)
- 示例
<img src="http://www.w3school.com.cn/i/eg_tulip.jpg" alt="tulip" id="tulip" style="margin-left:0px;" />
document.getElementById("tulip").onload=function(){
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("tulip");
ctx.drawImage(img,90,130,90,80,20,20,90,80);
};

2.7 陰影
- 2D 上下文會(huì)根據(jù)以下幾個(gè)屬性的值,自動(dòng)為形狀或路徑繪制出陰影。
| 屬性 | 描述 |
|---|---|
| shadowColor | 用CSS 顏色格式表示的陰影顏色,默認(rèn)為黑色。 |
| shadowBlur | 模糊的像素?cái)?shù),默認(rèn)0,即不模糊。 |
| shadowOffsetX | 形狀或路徑x 軸方向的陰影偏移量,默認(rèn)為0。 |
| shadowOffsetY | 形狀或路徑y(tǒng) 軸方向的陰影偏移量,默認(rèn)為0。 |
- 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
//設(shè)置陰影
context.shadowOffsetX = 15;
context.shadowOffsetY = 15;
context.shadowBlur = 5;
context.shadowColor = "rgba(0, 0, 0, 0.5)";
//繪制紅色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//繪制藍(lán)色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);

2.8 漸變
- 漸變由CanvasGradient 實(shí)例表示,很容易通過2D 上下文來創(chuàng)建和修改。
方法| 描述
-|-
createLinearGradient()| 創(chuàng)建線性漸變(用在畫布內(nèi)容上)
createRadialGradient()| 創(chuàng)建放射狀/環(huán)形的漸變(用在畫布內(nèi)容上)
addColorStop() |規(guī)定漸變對象中的顏色和停止位置
(1)createLinearGradient()
- createLinearGradient() 方法創(chuàng)建線性的漸變對象。
- 漸變可用于填充矩形、圓形、線條、文本等等
- JavaScript 語法
context.createLinearGradient(x0,y0,x1,y1);
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var grd=ctx.createLinearGradient(0,0,170,0);
grd.addColorStop(0,"white");
grd.addColorStop(1,"red");
ctx.fillStyle=grd;
ctx.fillRect(20,20,150,100);

(2)createRadialGradient()
- createLinearGradient() 方法創(chuàng)建放射狀/圓形漸變對象。
- 漸變可用于填充矩形、圓形、線條、文本等等。
- JavaScript 語法
context.createRadialGradient(x0,y0,r0,x1,y1,r1);
- 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
var gradient = context.createRadialGradient(55, 55, 10, 55, 55, 30);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "red");
//繪制漸變矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 150, 100);

2.9 模式
- createPattern() 方法在指定的方向內(nèi)重復(fù)指定的元素。
- 元素可以是圖片、視頻,或者其他 <canvas> 元素。
- 被重復(fù)的元素可用于繪制/填充矩形、圓形或線條等等。
- JavaScript 語法
context.createPattern(image,"repeat|repeat-x|repeat-y|no-repeat");
- 示例
<img src="http://www.w3school.com.cn/i/lamp.gif" id="lamp" />
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
var image = document.getElementById("lamp"),
pattern = context.createPattern(image, "repeat");
//繪制矩形
context.fillStyle = pattern;
context.fillRect(0, 0, 160, 130);

2.10 像素操作與使用圖像數(shù)據(jù)
- 2D 上下文 支持像素操作和使用圖像數(shù)據(jù)
| 方法 | 描述 |
|---|---|
| createImageData() | 創(chuàng)建新的、空白的 ImageData 對象 |
| getImageData() | 返回 ImageData 對象,該對象為畫布上指定的矩形復(fù)制像素?cái)?shù)據(jù) |
| putImageData() | 把圖像數(shù)據(jù)(從指定的 ImageData 對象)放回畫布上 |
- 每個(gè)ImageData 對象都有三個(gè)屬性:width、height 和data
| 屬性 | 描述 |
|---|---|
| width | 返回 ImageData 對象的寬度 |
| height | 返回 ImageData 對象的高度 |
| data | 返回一個(gè)對象,其包含指定的 ImageData 對象的圖像數(shù)據(jù) |
- data 屬性是一個(gè)數(shù)組,保存著圖像中每一個(gè)像素的數(shù)據(jù)。對于ImageData對象中的每個(gè)像素,都存在著四方面的信息,即 RGBA 值:
| 元素 | 值 |
|---|---|
| R | 紅色 (0-255) |
| G | 綠色 (0-255) |
| B | 藍(lán)色 (0-255) |
| A | alpha 通道 (0-255; 0 是透明的,255 是完全可見的) |
(1)createImageData()
- createImageData() 方法創(chuàng)建新的空白 ImageData 對象。新對象的默認(rèn)像素值 transparent black。
- javascript 語法
/**語法一,以指定的尺寸(以像素計(jì))創(chuàng)建新的 ImageData 對象**/
var imgData=context.createImageData(width,height);
/**語法二,創(chuàng)建與指定的另一個(gè) ImageData 對象尺寸相同的新 ImageData 對象(不會(huì)復(fù)制圖像數(shù)據(jù))**/
var imgData=context.createImageData(imageData);
- 示例
/**創(chuàng)建 100*100 像素的 ImageData 對象,其中每個(gè)像素都是綠色的,然后把它放到畫布上**/
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var imgData=ctx.createImageData(100,100);
for (var i=0;i<imgData.data.length;i+=4)
{
imgData.data[i+0]=0;
imgData.data[i+1]=255;
imgData.data[i+2]=0;
imgData.data[i+3]=255;
}
ctx.putImageData(imgData,10,10);

(2)getImageData()、putImageData()
- getImageData() 方法返回ImageData對象,該對象拷貝了畫布指定矩形的像素?cái)?shù)據(jù)。
- putImageData() 方法將圖像數(shù)據(jù)(從指定的 ImageData 對象)放回畫布上。
- javascript 語法
var imgData=context.getImageData(x,y,width,height);
context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
- 示例
<img src="http://www.w3school.com.cn/i/eg_tulip.jpg" alt="tulip" id="tulip" style="margin-left:0px;" />
/**使用 getImageData() 來反轉(zhuǎn)畫布上的圖像的每個(gè)像素的顏色**/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("tulip");
ctx.drawImage(img,0,0);
var imgData = ctx.getImageData(0,0,c.width,c.height);
for(var i= 0; i<imgData.data.length; i+=4){
imgData.data[i] = 255-imgData.data[i];
imgData.data[i+1] = 255- imgData.data[i+1];
imgData.data[i+2] = 255-imgData.data[i+2];
imgData.data[i+3] = 255;
}
ctx.putImageData(imgData,0,0);

2.11合成
- 有兩個(gè)會(huì)應(yīng)用到2D 上下文中所有繪制操作的屬性:globalAlpha和globalComposition-Operation
| 屬性 | 描述 |
|---|---|
| globalAlpha | 設(shè)置或返回繪圖的當(dāng)前 alpha 或透明值 |
| globalCompositeOperation | 設(shè)置或返回新圖像如何繪制到已有的圖像上 |
(1)globalAlpha()
globalAlpha 屬性設(shè)置或返回繪圖的當(dāng)前透明值(alpha 或 transparency)。
globalAlpha 是一個(gè)介于0 和1 之間的值(包括0 和1),用于指定所有繪制的透
明度。默認(rèn)值為0。javascript 語法
context.globalAlpha=number;
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(20,20,75,50);
// 調(diào)節(jié)透明度
ctx.globalAlpha=0.2;
ctx.fillStyle="blue";
ctx.fillRect(50,50,75,50);
ctx.fillStyle="green";
ctx.fillRect(80,80,75,50);

(2)globalCompositeOperation()
- globalCompositeOperation屬性設(shè)置或返回如何將一個(gè)源(新的)圖像繪制到目標(biāo)(已有)的圖像上。
- 源圖像 = 您打算放置到畫布上的繪圖。
- 目標(biāo)圖像 = 您已經(jīng)放置在畫布上的繪圖。
- javascript 語法
context.globalCompositeOperation="source-in";
- 屬性值
| 值 | 描述 |
|---|---|
| source-over | 默認(rèn)。在目標(biāo)圖像上顯示源圖像。 |
| source-atop | 在目標(biāo)圖像頂部顯示源圖像。源圖像位于目標(biāo)圖像之外的部分是不可見的。 |
| source-in | 在目標(biāo)圖像中顯示源圖像。只有目標(biāo)圖像內(nèi)的源圖像部分會(huì)顯示,目標(biāo)圖像是透明的。 |
| source-out | 在目標(biāo)圖像之外顯示源圖像。只會(huì)顯示目標(biāo)圖像之外源圖像部分,目標(biāo)圖像是透明的。 |
| destination-over | 在源圖像上方顯示目標(biāo)圖像。 |
| destination-atop | 在源圖像頂部顯示目標(biāo)圖像。源圖像之外的目標(biāo)圖像部分不會(huì)被顯示。 |
| destination-in | 在源圖像中顯示目標(biāo)圖像。只有源圖像內(nèi)的目標(biāo)圖像部分會(huì)被顯示,源圖像是透明的。 |
| destination-out | 在源圖像外顯示目標(biāo)圖像。只有源圖像外的目標(biāo)圖像部分會(huì)被顯示,源圖像是透明的。 |
| lighter | 顯示源圖像 + 目標(biāo)圖像。 |
| copy | 顯示源圖像。忽略目標(biāo)圖像。 |
| xor | 使用異或操作對源圖像與目標(biāo)圖像進(jìn)行組合。 |
- 示例
<!DOCTYPE html>
<html>
<head>
<style>
canvas{
border:1px solid #d3d3d3;
margin-right:10px;
margin-bottom:20px;
}
</style>
</head>
<body>
<script>
var gco=new Array();
gco.push("source-atop");
gco.push("source-in");
gco.push("source-out");
gco.push("source-over");
gco.push("destination-atop");
gco.push("destination-in");
gco.push("destination-out");
gco.push("destination-over");
gco.push("lighter");
gco.push("copy");
gco.push("xor");
for (n=0;n<gco.length;n++)
{
document.write("<div id='p_" + n + "' style='float:left;'>" + gco[n] + ":<br>");
var c=document.createElement("canvas");
c.width=120;
c.height=100;
document.getElementById("p_" + n).appendChild(c);
var ctx=c.getContext("2d");
ctx.fillStyle="blue";
ctx.fillRect(10,10,50,50);
ctx.globalCompositeOperation=gco[n];
ctx.beginPath();
ctx.fillStyle="red";
ctx.arc(50,50,30,0,2*Math.PI);
ctx.fill();
document.write("</div>");
}
</script>
</body>
</html>

2.12 線條樣式
- 2D 上下文中繪制操作中還具有相應(yīng)的線條樣式屬性。
屬性| 描述
-|-
lineCap| 設(shè)置或返回線條的結(jié)束端點(diǎn)樣式
lineJoin| 設(shè)置或返回兩條線相交時(shí),所創(chuàng)建的拐角類型
lineWidth| 設(shè)置或返回當(dāng)前的線條寬度
miterLimit| 設(shè)置或返回最大斜接長度
(1)lineWidth
- lineWidth 屬性設(shè)置或返回當(dāng)前線條的寬度,以像素計(jì)。
- javascript語法
context.lineWidth=number;
- 示例
//用寬度為 10 像素的線條來繪制矩形
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth=10;
ctx.strokeRect(20,20,80,100);

(2)lineCap
- lineCap 屬性設(shè)置或返回線條末端線帽的樣式。
- javascript 語法
context.lineCap="butt|round|square";
- 屬性值
| 值 | 描述 |
|---|---|
| butt | 默認(rèn)。向線條的每個(gè)末端添加平直的邊緣。 |
| round | 向線條的每個(gè)末端添加圓形線帽。 |
| square | 向線條的每個(gè)末端添加正方形線帽。 |
- 示例
//三種不同的線帽
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineWidth=10;
ctx.lineCap="butt";
ctx.moveTo(20,20);
ctx.lineTo(200,20);
ctx.stroke();
ctx.beginPath();
ctx.lineCap="round";
ctx.moveTo(20,40);
ctx.lineTo(200,40);
ctx.stroke();
ctx.beginPath();
ctx.lineCap="square";
ctx.moveTo(20,60);
ctx.lineTo(200,60);
ctx.stroke();

(2)lineJoin
- lineJoin 屬性設(shè)置或返回所創(chuàng)建邊角的類型,當(dāng)兩條線交匯時(shí)。
- javascript語法
context.lineJoin="bevel|round|miter";
- 屬性值
| 值 | 描述 |
|---|---|
| bevel | 創(chuàng)建斜角。 |
| round | 創(chuàng)建圓角。 |
| miter | 默認(rèn)。創(chuàng)建尖角 |
- 示例
/**當(dāng)兩條線條交匯時(shí),分別創(chuàng)建斜角、圓形、尖角邊角**/
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineWidth=20;
ctx.lineJoin="bevel";
ctx.moveTo(20,20);
ctx.lineTo(100,50);
ctx.lineTo(20,100);
ctx.stroke();
ctx.beginPath();
ctx.lineWidth=20;
ctx.lineJoin="round";
ctx.moveTo(100,20);
ctx.lineTo(180,50);
ctx.lineTo(100,100);
ctx.stroke();
ctx.beginPath();
ctx.lineWidth=20;
ctx.lineJoin="miter";
ctx.moveTo(180,20);
ctx.lineTo(260,50);
ctx.lineTo(180,100);
ctx.stroke();

(4)miterLimit
miterLimit 屬性設(shè)置或返回最大斜接長度。
-
斜接長度指的是在兩條線交匯處內(nèi)角和外角之間的距離。
斜度 只有當(dāng) lineJoin 屬性為 "miter" 時(shí),miterLimit 才有效。
邊角的角度越小,斜接長度就會(huì)越大。
為了避免斜接長度過長,我們可以使用 miterLimit 屬性。
如果斜接長度超過 miterLimit 的值,邊角會(huì)以 lineJoin 的 "bevel" 類型來顯示

- javascript語法
context.miterLimit=number;
- 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth=10;
ctx.lineJoin="miter";
ctx.beginPath();
ctx.miterLimit=5;
ctx.moveTo(20,20);
ctx.lineTo(50,27);
ctx.lineTo(20,34);
ctx.stroke();
ctx.beginPath();
ctx.miterLimit=3;
ctx.moveTo(80,20);
ctx.lineTo(110,27);
ctx.lineTo(80,34);
ctx.stroke();

2.13 其它
- 有兩個(gè)方法可以跟蹤上下文的狀態(tài)變化。
- 如果你知道將來還要返回某組屬性與變換的組合,可以調(diào)用save()方法。調(diào)用這個(gè)方法后,當(dāng)時(shí)的所有設(shè)置都會(huì)進(jìn)入一個(gè)棧結(jié)構(gòu),得以妥善保管。
- 然后可以對上下文進(jìn)行其他修改。等想要回到之前保存的設(shè)置時(shí),可以調(diào)用restore()方法,在保存設(shè)置的棧結(jié)構(gòu)中向前返回一級(jí),恢復(fù)之前的狀態(tài)。
- 連續(xù)調(diào)用save()可以把更多設(shè)置保存到棧結(jié)構(gòu)中,之后再連續(xù)調(diào)用restore()則可以一級(jí)一級(jí)返回。
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
context.strokeStyle = "red";
context.translate(10, 10);
context.save();
context.strokeStyle = "blue";
context.translate(40, 40);
context.save();
context.strokeStyle = "green";
context.strokeRect(0, 0, 20, 20); //繪制綠色矩形
context.restore();
context.strokeRect(40, 40, 20, 20); //繪制藍(lán)色矩形
context.restore();
context.strokeRect(0, 0, 20, 20); //繪制紅色矩形

