一、簡介
HTML5 中的定義:“它是依賴分辨率的位圖畫布,你可以在 canvas 上面繪制任何圖形,甚至加載照片。”
- 矩形空白區域
- 通過 javascript 繪制圖形
- 可以加載圖片
二、HTML 部分
<canvas id="a" width="300" height="300">您的瀏覽器不支持 canvas</canvas>
簡單的在 HTML 頁面添加一個 canvas
元素,設定寬高,添加 id
便于 javascript
獲取。
- 每個
canvas
初始都是一個白板。 - 樣式除了寬高,盡量寫在畫布里,而不是使用 CSS
-
canvas
標簽里如果添加文本,那么當瀏覽器不支持canvas
時顯示文本
三、繪圖上下文環境
var a = document.getElementById('a');
var a_context = a.getContext("2d");
- 獲取到
canvas
元素 - 調用它的
getContext()
方法獲取繪圖上下文環境,參數必須為2d
,未來可能會有3d
- 基于上下文環境的方法進行繪圖
繪圖上下文包含所有繪制方法和屬性的定義。
四、路徑
4.1 beginPath()
開始新路徑
表示重新開始新的路徑。
canvas 是基于狀態的繪圖,開啟一條新的路徑,就可以設置新的狀態。但是 beginPath()
不會將狀態重置回默認值。
同一條路徑上的線條和曲線都會是相同的顏色。所以需要繪制不同顏色的時候,必須開啟新的路徑。
4.2 closePath()
結束路徑
用于結束路徑,與 beginPath()
并不一定成對出現。
注意:默認結束路徑后,圖形自動封閉,即首尾相連。所以有些時候不會用到結束路徑。
4.3 stroke()
繪制路徑
繪制已定義的路徑
4.4 fill()
填充路徑
將準備畫的路徑塊填充
fill()
會覆蓋描邊 stroke()
邊框的一半。所以,在需要描邊的填充色,需要先填充,后描邊。
4.5 isPointInPath()
是否在路徑中
如果指定的點位于當前路徑中,則返回 true,否則返回 false
context.isPointInPath(x,y);
-
x
測試點的 x 坐標 -
y
測試點的 y 坐標
4.6 clip()
剪切
從原始畫布剪切任意形狀和尺寸的區域
context.clip();
注意:一旦剪切了某個區域,則所有之后的繪圖都會被限制在被剪切的區域內(不能訪問畫布上的其他區域)。您也可以在使用
clip()
方法前通過使用save()
方法對當前畫布區域進行保存,并在以后的任意時間通過restore()
方法進行恢復。
五、線條以及填充顏色
5.1 fillStyle
填充樣式
設置或返回用于填充繪畫的顏色、漸變或模式,需要在填充前聲明才有效
context.fillStyle=color|gradient|pattern;
-
color
指示繪圖填充色的 CSS 顏色值。默認值是 #000000。 -
gradient
用于填充繪圖的漸變對象 -
pattern
用于填充繪圖的pattern
對象
5.2 strokeStyle
線條樣式
設置或返回用于筆觸的顏色、漸變或模式,需要在繪制前聲明才有效
context.strokeStyle=color|gradient|pattern;
-
color
指示繪圖筆觸顏色的 CSS 顏色值。默認值是 #000000。 -
gradient
用于填充繪圖的漸變對象 -
pattern
用于創建pattern
筆觸的pattern
對象
5.3 lineCap
線條結束端點樣式
設置或返回線條的結束端點樣式
context.lineCap="butt|round|square";
-
butt
默認。向線條的每個末端添加平直的邊緣。 -
round
向線條的每個末端添加圓形線帽。 -
square
向線條的每個末端添加正方形線帽。
round
和 square
會使線條略微變長。
5.4 lineJoin
線條拐角類型
設置或返回兩條線相交時,所創建的拐角類型
context.lineJoin="bevel|round|miter";
-
bevel
創建斜角 -
round
創建圓角 -
miter
默認。創建尖角
5.5 lineWidth
線條寬度
設置或返回當前的線條寬度
context.lineWidth=number;
-
number
當前線條的寬度,以像素計
5.6 miterLimit
線條最大斜接長度
設置或返回最大斜接長度
context.miterLimit=number;
-
number
正數
如果斜接長度超過miterLimit
的值,邊角會以lineJoin
的bevel
類型來顯示。
斜接長度指的是在兩條線交匯處內角和外角之間的距離。
只有當 lineJoin
屬性為 miter
時,miterLimit
才有效。
邊角的角度越小,斜接長度就會越大。
為了避免斜接長度過長,我們可以使用 miterLimit 屬性。
如果斜接長度超過 miterLimit 的值,邊角會以 lineJoin 的 "bevel" 類型來顯示(圖解 3):
六、直線路徑
6.1 moveTo()
起點坐標
把路徑移動到畫布中的指定點,不創建線條。聲明直線開始的起點坐標。括號里面填寫坐標。
context.moveTo(100,100);
6.2 lineTo()
終點坐標
聲明直線結束的終點坐標。括號里面填寫坐標。
context.moveTo(100,100);//起點
context.lineTo(700,700);//終點
連續出現相當于以前一個為起點繼續走向另一個坐標。
context.moveTo(100,100);//起點
context.lineTo(700,700);//終點
context.lineTo(100,700);//以前一個終點為起點坐標
當 lineTo()
在 beginPath()
后面使用時,可以代替 moveTo()
,和 moveTo()
起到相同效果。
6.3 多邊形
從 moveTo()
開始,使用 lineTo()
畫直線到三個頂點,最終回到起點坐標。
如三角形:
//路徑描述
context.moveTo(100,100);
context.lineTo(700,700);
context.lineTo(100,700);
context.lineTo(100,100);
//繪制
context.stroke();
七、貝塞爾曲線
7.1 quadraticCurveTo() 二次貝塞爾
通過使用表示二次貝塞爾曲線的指定控制點,向當前路徑添加一個點。
二次貝塞爾曲線需要兩個點。第一個點是用于二次貝塞爾計算中的控制點,第二個點是曲線的結束點。最后添加的是結束點
注意:曲線的開始點是當前路徑中最后一個點。如果路徑不存在,那么請使用
beginPath()
和moveTo()
方法來定義開始點。
context.quadraticCurveTo(cpx,cpy,x,y);
-
cpx
,cpy
貝塞爾控制點的坐標 -
x
,y
結束點的坐標
7.2 bezierCurveTo() 三次貝塞爾
通過使用表示三次貝塞爾曲線的指定控制點,向當前路徑添加一個點。
三次貝塞爾曲線需要三個點。前兩個點是用于三次貝塞爾計算中的控制點,第三個點是曲線的結束點。
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
-
cp1x
,cp1y
第一個貝塞爾控制點的坐標 -
cp2x
,cp2y
第二個貝塞爾控制點的坐標 -
x
,y
結束點的坐標
八、畫弧線、圓
8.1 arc()
創建圓路徑
創建弧/曲線(用于創建圓形或部分圓)
context.arc(centerX, centerY, radius, startingAngle, endingAngle, anticlockwise=true);
-
centerx
,centery
表示圓心位置 -
radius
表示半徑 -
startingAngle
,endingAngle
表示開始位置和結束位置 -
anticlockwise
表示true
時為順時針繪制,false
為逆時針繪制。默認為true
其中角度參數的值:0
表示圓的最右邊,0.5*Math.PI
表示最下面,1*Math.PI
表示最左邊,1.5*Math.PI
表示最上面,2*Math.PI
表示最右邊。這些規定是固定的,不會因為順逆時針改變。
8.2 arcTo()
兩切線弧
創建兩切線之間的弧/曲線
context.fillRect(x1,y1,x2,y2,r);
-
x1
,y1
弧的起點坐標 -
x2
,y2
弧的終點坐標 -
r
弧的半徑
使用 stroke()
方法在畫布上繪制確切的弧。
8.3 繪制
-
lineWidth
定義線條粗細 -
strokeStyle
定義描邊樣式 -
stroke()
描邊 -
fillStyle
定義填充樣式 -
fill()
填充
8.4 圓
context.arc(100,100,80,0,2*Math.PI,true);
表示從右邊(0)開始,順時針畫圓,到右邊(2 PI)結束。
九、文本
不同于網頁中的文本,繪制在 canvas
中的文本是沒有盒模型的,沒有浮動、邊距、留白、自動換行等。
9.1 fillText()
填充文本
context.fillText("text",x,y);
-
text
規定在畫布上輸出的文本 -
x
,y
開始繪制文本的坐標位置
9.2 strokeText()
描邊文本
context.strokeText(text,x,y,maxWidth);
-
text
規定在畫布上輸出的文本 -
x
,y
開始繪制文本的坐標位置 -
maxWidth
可選。允許的最大文本寬度,以像素計
9.3 measureText()
測量文本寬度
measureText()
方法返回包含一個對象,該對象包含以像素計的指定字體寬度。
context.measureText(text).width;
- text 要測量的文本
9.4 font
字體樣式
canvas 中的字體會繼承 canvas 元素的字體大小和樣式風格。
設置 font
屬性覆蓋繼承值。符合 CSS 規則。
context.font = "bold 12px sans-serif";
屬性值里面的每個取值用空格隔開
- font style
- font variant
- font size
- font weight
- lineheight
- font family
使用相對字體大小,如
1.5em
或150%
,是基于canvas
元素本身的字體大小。rem
仍是基于根元素。
9.5 textAlign
對齊方式
類似 CSS 中的 text-align
。
context.textAlign = "start";
取值:start
(默認)、end
、left
、right
、center
。
9.6 textBaseline
相對于起點的位置
控制文本相對于起點的位置。
context.textBaseline = "top";
必須使用引號。
取值:top
、bottom
、hanging
、middle
、alphabetic
、ideographic
十、矩形
10.1 rect()
創建矩形
context.rect(x,y,width,height);
-
x
,y
矩形左上角的坐標 -
width
,height
矩形的寬高
使用 stroke()
或 fill()
方法在畫布上實際地繪制矩形。
10.2 fillRect()
已填充矩形
fillRect(x,y,width,height);
-
x
,y
表示矩形左上角坐標 -
width
,height
表示寬高
使用 fillStyle
屬性來設置用于填充繪圖的顏色、漸變或模式。
10.3 strokeRect()
已描邊矩形
strokeRect(x,y,width,height);
-
x
,y
表示矩形左上角坐標 -
width
,height
表示寬高
使用 strokeStyle
屬性來設置筆觸的顏色、漸變或模式。
10.4 clearRect()
清空矩形區域
context.clearRect(x,y,width,height);
-
x
,y
表示矩形左上角坐標 -
width
,height
表示寬高
十一、添加圖片
11.1 drawImage()
添加圖片
三種用法:
context.drawImage(img,x,y);
context.drawImage(img,x,y,width,height);
context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)
-
image
為圖片對象,必須 -
sx
,sy
為裁剪開始位置,左上角坐標,可選 -
sw
,sh
為裁剪寬高,可選 -
dx
,dy
為繪制起點,左上角坐標,必須 -
dw
,dh
為自定義的圖片寬高,可選
11.2 圖片對象
- 已存在的
<img>
元素
//HTML部分
<img id="cat" src="images/cat.png">
//javascript部分
window.onload = function() {
.
.
var cat = document.getElementById('cat');
context.drawImage(cat,0,0);
}
在 window.onload
事件處理器中,獲取已有圖片對象,然后在 canvas
中安全繪制圖片。
- 自己創建的圖片對象
var cat = new Image();
cat.src = "images/cat.png";
cat.onload = function() {
context.drawImage(cat,0,0);
};
創建圖片對象,然后在 cat.onload 事件處理器中安全地把圖片繪制在 canvas
中。
十二、特殊樣式
12.1 shadowColor
陰影顏色
設置或返回用于陰影的顏色
context.shadowColor=color;
-
color
用于陰影的 CSS 顏色值。默認值是 #000000。
12.2 shadowBlur
陰影模糊程度
設置或返回用于陰影的模糊級別
context.shadowBlur=number;
-
number
陰影的模糊級數
12.3 shadowOffsetX
陰影水平偏移
設置或返回陰影距形狀的水平距離
context.shadowOffsetX=number;
-
number
正值或負值,定義陰影與形狀的水平距離。
12.4 shadowOffsetY
陰影垂直偏移
設置或返回陰影距形狀的垂直距離
context.shadowOffsetY=number;
-
number
正值或負值,定義陰影與形狀的垂直距離
12.5 createPattern()
重復
在指定的方向內重復指定的元素。
元素可以是圖片、視頻,或者其他 canvas 元素。
被重復的元素可用于繪制/填充矩形、圓形或線條等等。
context.createPattern(image,"repeat|repeat-x|repeat-y|no-repeat");
-
image
規定要使用的圖片、畫布或視頻元素。 -
repeat
默認。該模式在水平和垂直方向重復。 -
repeat-x
該模式只在水平方向重復。 -
repeat-y
該模式只在垂直方向重復。 -
no-repeat
該模式只顯示一次(不重復)。
12.6 createLinearGradient()
創建線性漸變
調用 createLinearGradient()
方法創建線性漸變
createLinearGradient(x0,y0,x1,y1);
表示沿直線從(x0,y0)到(x1,y1)繪制漸變。
如水平漸變:
var my_gradient = context.createLinearGradient(0,0,300,0);
設置兩個 y
值為 0,漸變會沿水平從左到右。
注意:創建漸變需要賦給一個變量,通過這個變量設置色標
12.7 createRadialGradient()
創建徑向漸變
調用 createRadialGradient()
方法創建徑向漸變
createRadialGradient(x0,y0,r0,x1,y1,r1)
表示沿著兩個圓之間的錐面繪制漸變。
前三個參數代表開始圓,后三個參數表示結束圓。
12.8 addColorStop()
添加色標
addColorStop(index,color);
-
index
漸變位置,可以在 0 - 1 之間取任意值 -
color
漸變顏色,關鍵字及十六進制顏色要添加引號
注意:這個方法屬于創建的漸變對象,也就是前面創建漸變時的變量。
my_gradient.addColorStop(0,"block");
my_gradient.addColorStop(1,"white");
12.9 繪制漸變
context.fillStyle = my_gradient;
context.fillRect(0,0,300,225);
- 將填充顏色設置為創建的漸變
- 填充所需要的圖形
十三、轉換
轉換都應該放在繪制之前
13.1 scale() 縮放
縮放當前繪圖至更大或更小
注意:如果您對繪圖進行縮放,所有之后的繪圖也會被縮放。定位也會被縮放,線條大小也會被縮放。
context.scale(scalewidth,scaleheight);
-
scalewidth
縮放當前繪圖的寬度 (1=100%, 0.5=50%, 2=200%, 依次類推) -
scaleheight
縮放當前繪圖的高度 (1=100%, 0.5=50%, 2=200%, etc.)
13.2 rotate() 旋轉
旋轉當前繪圖
conntext.rotate(angle);
-
angle
旋轉角度,以弧度計。
將角度轉換為弧度,請使用 degrees*Math.PI/180
公式進行計算。
13.3 translate() 改變原點坐標
重新映射畫布上的 (0,0) 位置,改變坐標原點的位置
context.translate(x,y);
-
x
添加到水平坐標上的值 -
y
添加到垂直坐標上的值
當您在 translate()
之后調用諸如 fillRect()
之類的方法時,值會添加到 x
和 y
坐標值上。,即后面的繪圖涉及到坐標都會在此基礎上增加值。
13.4 transform() 變換矩陣
畫布上的每個對象都擁有一個當前的變換矩陣。
transform()
方法替換當前的變換矩陣。
它以下面描述的矩陣來操作當前的變換矩陣:
a c e
b d f
0 0 1
也就是說,transform()
允許您縮放、旋轉、移動并傾斜當前的環境。
注意:該變換只會影響
transform()
方法調用之后的繪圖。
前面的rotate()
,scale()
,translate()
,transform()
方法都會影響到當前的transform()
。
例如:如果您已經將繪圖設置為放到兩倍,則transform()
方法會把繪圖放大兩倍,您的繪圖最終將放大四倍。
context.transform(a,b,c,d,e,f);
-
a
水平縮放繪圖 -
b
水平傾斜繪圖 -
c
垂直傾斜繪圖 -
d
垂直縮放繪圖 -
e
水平移動繪圖 -
f
垂直移動繪圖
13.5 setTransform()
將當前轉換重置為單位矩陣。然后以同樣的參數運行 transform()
,這樣就可以不受前面的影響了。
context.setTransform(a,b,c,d,e,f);
-
a
水平縮放繪圖,默認值為 1 -
b
水平傾斜繪圖,默認值為 0 -
c
垂直傾斜繪圖,默認值為 0 -
d
垂直縮放繪圖,默認值為 1 -
e
水平移動繪圖,默認值為 0 -
f
垂直移動繪圖,默認值為 0
所以矩陣默認為單位矩陣:
1 0 0
0 1 0
0 0 1
13.6 save()、 restore()
-
save()
保存當前環境的狀態- 原點位置
- 縮放大小
- 旋轉
- 矩陣變換
- 裁剪塊
-
restore()
返回之前保存過的路徑狀態和屬性
十四 ImageData
對象
對于 ImageData
對象中的每個像素,都存在著四方面的信息,即 RGBA 值:
- R - 紅色 (0-255)
- G - 綠色 (0-255)
- B - 藍色 (0-255)
- A - alpha 通道 (0-255; 0 是透明的,255 是完全可見的)
因此 ,transparent black
表示 (0,0,0,0)
。
color/alpha
以數組形式存在,并且既然數組包含了每個像素的四條信息,數組的大小是 ImageData
對象的四倍。獲得數組大小的辦法,就是使用 ImageDataObject.data.length
包含 color/alpha
信息的數組存儲于 ImageData
對象的 data
屬性中。
14.1 createImageData()
創建 ImageData 對象
創建新的空白 ImageData
對象。
有兩個版本的 createImageData()
方法:
//以指定的尺寸(以像素計)創建新的 ImageData 對象
var imgData=context.createImageData(width,height);
//創建與指定的另一個 ImageData 對象尺寸相同的新 ImageData 對象(不會復制圖像數據)
var imgData=context.createImageData(imageData);
新對象的默認像素值 transparent black
。
-
width
ImageData 對象的寬度,以像素計。 -
height
ImageData 對象的高度,以像素計。 -
imageData
另一個 ImageData 對象。
14.2 getImageData()
復制畫布像素數據
返回 ImageData
對象,該對象拷貝了畫布指定矩形的像素數據,進行操作后,通過 putImageData()
將圖像數據放回畫布
var imgData = context.getImageData(x,y,width,height);
-
x
,y
開始復制的左上角位置的坐標 -
width
,height
將要復制的矩形區域的寬高
14.3 putImageData()
放入像素數據
將圖像數據(從指定的 ImageData 對象)放回畫布上。
context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
-
imgData
規定要放回畫布的 ImageData 對象 -
x
,y
ImageData 對象放置在畫布上的位置左上角的坐標,以像素計 -
dirtyX
,dirtyY
可選。以像素計,在畫布上繪制的圖像在 ImageData 對象上的位置坐標 -
dirtyWidth
,dirtyHeight
可選。在畫布上繪制圖像的寬高
后面四個屬性相當于裁剪,但是,在畫布上,依然是整個 ImageData 對象。
如:
var imgData=ctx.getImageData(10,10,50,50);
ctx.putImageData(imgData,10,70,20,40,30,10);
在畫布上放置裁剪部分的位置就變成了(10+20,70+40),寬高是 30, 10。
注意:如果裁剪位置加上裁剪寬度,超出了原來的寬高,超出部分不會繪制
14.4 width
、height
寬高
返回 ImageData 對象的寬高,以像素計。
imgData.width;
imgData.height;
14.5 data
圖像數據
返回一個對象,該對象包含指定的 ImageData 對象的圖像數據。
對于 ImageData 對象中的每個像素,都存在著四方面的信息,即 RGBA 值:
R - 紅色 (0-255)
G - 綠色 (0-255)
B - 藍色 (0-255)
A - alpha 通道 (0-255; 0 是透明的,255 是完全可見的)
color/alpha 以數組形式存在,并存儲于 ImageData 對象的 data 屬性中。
將 ImageData 對象中的第一個像素變為紅色的語法:
imgData=ctx.createImageData(100,100);
imgData.data[0]=255;
imgData.data[1]=0;
imgData.data[2]=0;
imgData.data[3]=255;
將 ImageData 對象中的第二個像素變為綠色的語法:
imgData=ctx.createImageData(100,100);
imgData.data[4]=0;
imgData.data[5]=255;
imgData.data[6]=0;
imgData.data[7]=255;
十五、合成
15.1 globalAlpha
透明度
設置或返回繪圖的當前 alpha 或透明值
context.globalAlpha=number;
-
number
透明值。必須介于 0.0(完全透明) 與 1.0(不透明) 之間。
15.2 globalCompositeOperation
設置或返回新圖像如何繪制到已有的圖像上
源圖像 = 您打算放置到畫布上的繪圖。
目標圖像 = 您已經放置在畫布上的繪圖。
context.globalCompositeOperation="source-in";
-
source-over
默認。在目標圖像上顯示源圖像。 -
source-atop
在目標圖像頂部顯示源圖像。源圖像位于目標圖像之外的部分是不可見的。 -
source-in
在目標圖像中顯示源圖像。只有目標圖像內的源圖像部分會顯示,目標圖像是透明的。 -
source-out
在目標圖像之外顯示源圖像。只會顯示目標圖像之外源圖像部分,目標圖像是透明的。 -
destination-over
在源圖像上方顯示目標圖像。 -
destination-atop
在源圖像頂部顯示目標圖像。源圖像之外的目標圖像部分不會被顯示。 -
destination-in
在源圖像中顯示目標圖像。只有源圖像內的目標圖像部分會被顯示,源圖像是透明的。 -
destination-out
在源圖像外顯示目標圖像。只有源圖像外的目標圖像部分會被顯示,源圖像是透明的。 -
lighter
顯示源圖像 + 目標圖像。 -
copy
顯示源圖像。忽略目標圖像。 -
xor
使用異或操作對源圖像與目標圖像進行組合。
十六、兼容IE
雖然 IE 瀏覽器不支持 canvas API
,但是他有一個叫 VML
的技術,可以完成 canvas
元素能做的大部分工作。
16.1 ExplorerCanvas——excanvas.js
excanvas.js 是一個開源的,采用 Apache license 許可的 javascript 類庫,在 IE 中實現了 canvas 的 API。
<!--[if lt IE9]>
<script src="excanvas.js"></script>
<![endif]-->
16.2 限制
- 顏色漸變只支持線性漸變
- 模式必須在兩個方向上重復
- 不支持裁剪
- 非等比縮放
- 很慢