## Canvas
**二、canvas**
HTML5`<canvas>`元素用于圖形的繪制,通過腳本 (通常是JavaScript)來完成。
`<canvas> `標簽只是圖形容器,您必須使用腳本來繪制圖形。
要使用Canvas API,首先需要新建一個`<canvas>`網頁元素
```
<canvas id="canvas" width="400" height="200">
您的瀏覽器不支持canvas!
</canvas>
```
width 和 height 屬性定義的畫布的大小。
接著,我們可以通過標簽選擇獲取到<canvas>元素:
```
var canvas = document.getElementById('canvas');
```
然后,創建context對象:
```
if(canvas.getContext){
var ctx = canvas.getContext('2d');
}
```
調用getContext()方法時,傳遞一個“2d”參數,會獲得一個CanvasRenderingContext2D對象,使用該對象可以在畫布上繪制二維圖形。我們也可將CanvasRenderingContext2D簡稱為“上下文對象”。
**2.1 canvas的繪圖用法**
canvas畫布提供了一個用來作圖的平面空間,該空間的每個點都有自己的坐標,x表示橫坐標,y表示豎坐標。原點(0, 0)位于圖像左上角,x軸的正向是原點向右,y軸的正向是原點向下。
**(1)繪制矩形**
- rect(x,y,width,height)方法用來繪制矩形。
- fillRect(x, y, width, height)方法用來繪制矩形,它的四個參數分別為矩形左上角頂點的x坐標、y坐標,以及矩形的寬和高。fillStyle屬性用來設置矩形的填充色。
- strokeRect(x, y, width, height)方法同樣是繪制矩形,但只畫線不填充,也可以說是畫空心矩形。strokeStyle屬性用來設置矩形的繪制色。
- clearRect(x, y, width, height)方法用來清除某個矩形區域的內容。
**(2)繪制圓形和扇形**
- arc(x, y, radius, startAngle, endAngle, anticlockwise)方法用來繪制圓形和扇形。
arc方法的x和y參數是圓心坐標,radius是半徑,startAngle和endAngle則是扇形的起始角度和終止角度(以弧度表示),anticlockwise表示做圖時應該逆時針畫(true)還是順時針畫(false)。
- arcTo(x1,y1,x2,y2,r)方法在畫布上創建介于兩個切線之間的弧/曲線。
參數:x1 弧的起點的 x 坐標,y1 弧的起點的 y 坐標,x2 弧的終點的 x 坐標,y2 弧的終點的 y 坐標,r 弧的半徑。
**(3)繪制文本**
- fillText(string, x, y) 用來繪制文本,它的三個參數分別為文本內容、起點的x坐標、y坐標。使用之前,需用font設置字體、大小、樣式(寫法類似與CSS的font屬性)。
strokeText(string,x,y)方法,用來添加空心字。
```
// 設置字體
ctx.font = "Bold 20px Arial";
// 設置對齊方式,start、end、right、center
ctx.textAlign = "left";
// 設置填充顏色
ctx.fillStyle = "#008600";
//設置垂直對齊方式,top、hanging、middle、alphabetic、ideographic、bottom
ctx.textBaseline = top;
```
我們還可以計算字體寬度(px):
```
var name = 'aaa';
ctx.measureText(name);
```
measureText() 方法返回包含一個對象,該對象包含以像素計的指定字體寬度。
```
ctx.measureText(name).width
```
**(4)繪制路徑**
`beginPath()`方法表示開始繪制路徑,`moveTo(x, y)`方法設置線段的起點,`lineTo(x, y)`方法設置線段的終點,`stroke()`方法用來給透明的線段著色。
```
ctx.beginPath(); // 開始路徑繪制
ctx.moveTo(20, 20); // 設置路徑起點,坐標為(20,20)
ctx.lineTo(200, 20); // 繪制一條到(200,20)的直線
ctx.lineWidth = 1.0; // 設置線寬
ctx.strokeStyle = '#CC0000'; // 設置線的顏色
ctx.stroke(); // 進行線的著色,這時整條線才變得可見
moveTo()和lineTo()方法可以多次使用。
```
注意:如果使用closePath()方法,會自動繪制一條當前點到起點的直線,形成一個封閉圖形。
fill()和stroke()分別填充當前繪圖(路徑)和繪制已定義的路徑。
**isPointInPath()**
```
isPointInPath(x,y);
```
如果指定的點位于當前路徑中,isPointInPath() 方法返回 true,否則返回 false。
**clip()**
clip()方法從原始畫布中剪切任意形狀和尺寸。
注意:一旦剪切了某個區域,則所有之后的繪圖都會被限制在被剪切的區域內(不能訪問畫布上的其他區域)。您也可以在使用 clip() 方法前通過使用 save() 方法對當前畫布區域進行保存,并在以后的任意時間對其進行恢復(通過 restore() 方法)。
closePath()方法創建當前點回到起始點的路徑。
**其他樣式屬性:**
- lineCap 設置或返回線條的結束端點樣式,可能值: butt|round|square(平直邊緣|圓形線帽|正方形線帽)
- lineJoin 設置或返回兩條線相交時,所創建的拐角類型,可能值:bevel|round|miter(斜角|圓角|尖角(默認值))
- lineWidth 設置或返回當前的線條寬度。
- miterLimit 正數,設置或返回最大斜接長度。如果斜接長度超過 miterLimit 的值,邊角會以 lineJoin 的 "bevel" 類型來顯示。
- fillStyle 設置填充色
- strokeStyle 設置繪制線色
顏色格式:
```
//可直接用顏色名稱
'red' 'green'
//十六進制顏色
'#d9d9d9'
//rgb
rgb(0,0,0)
//rgba
rgba(0,0,0,1)
```
**(5)設置漸變色**
**線性漸變**
createLinearGradient方法用來設置漸變色。
```
var gradient = ctx.createLinearGradient(0, 0, 0, 160);
gradient.addColorStop(0, "#BABABA");
gradient.addColorStop(1, "#636363");
```
createLinearGradient()方法的參數是(x1, y1, x2, y2),其中x1和y1是起點坐標,x2和y2是終點坐標。通過不同的坐標值,可以生成從上至下、從左到右的漸變等等。
使用方法:
```
ctx.fillStyle = myGradient;
ctx.fillRect(10,10,200,100);
```
**環形漸變**
createRadialGradient()方法的參數是(x0,y0,r0,x1,y1,r1),其中x0 漸變的開始圓的 x 坐標,y0 漸變的開始圓的 y 坐標,r0 開始圓的半徑,x1 漸變的結束圓的 x 坐標,y1 漸變的結束圓的 y 坐標,r1 結束圓的半徑。
```
var grd=ctx.createRadialGradient(75,50,5,90,60,100);
grd.addColorStop(0,"red");
grd.addColorStop(1,"white");
ctx.fillStyle=grd;
ctx.fillRect(10,10,150,100);
```
**(6)設置陰影**
我們還可以設置陰影
```
ctx.shadowOffsetX = 10; // 設置水平位移
ctx.shadowOffsetY = 10; // 設置垂直位移
ctx.shadowBlur = 5; // 設置模糊度
ctx.shadowColor = "rgba(0,0,0,0.5)"; // 設置陰影顏色
ctx.fillStyle = "#CC0000";
ctx.fillRect(10,10,200,100);
```
**(7)合成**
`globalAlpha` 屬性設置或返回繪圖的當前透明值(alpha 或 transparency)。
`globalAlpha` 屬性值必須是介于 0.0(完全透明) 與 1.0(不透明) 之間的數字。
ctx.globalAlpha = number
`globalCompositeOperation`屬性設置或返回如何將一個源(新的)圖像繪制到目標(已有的)的圖像上。
源圖像 = 您打算放置到畫布上的繪圖。
目標圖像 = 您已經放置在畫布上的繪圖。
```
source-over 默認。在目標圖像上顯示源圖像。
source-atop 在目標圖像頂部顯示源圖像。源圖像位于目標圖像之外的部分是不可見的。
source-in 在目標圖像中顯示源圖像。只有目標圖像之內的源圖像部分會顯示,目標圖像是透明的。
source-out 在目標圖像之外顯示源圖像。只有目標圖像之外的源圖像部分會顯示,目標圖像是透明的。
destination-over 在源圖像上顯示目標圖像。
destination-atop 在源圖像頂部顯示目標圖像。目標圖像位于源圖像之外的部分是不可見的。
destination-in 在源圖像中顯示目標圖像。只有源圖像之內的目標圖像部分會被顯示,源圖像是透明的。
destination-out 在源圖像之外顯示目標圖像。只有源圖像之外的目標圖像部分會被顯示,源圖像是透明的。
lighter 顯示源圖像 + 目標圖像。
copy 顯示源圖像。忽略目標圖像。
xor 使用異或操作對源圖像與目標圖像進行組合。
```
**2.2 繪制圖像**
Canvas API 允許將圖像文件插入畫布。
我們可以使用Image對象來加載圖片,然后繪制:
```
var image = new Image();
image.onload = function(){
ctx.drawImage(image,0,0);
};
image.src='new.jpg';
```
**drawImage方法**
```
drawImage(img,x,y)
drawImage(img,x,y,width,height)
drawImage(img,sx,sy,switch,sheight,x,y,width,height)
```
參數:
img 規定要使用的圖像、畫布或視頻;sx 可選,開始剪切的 x 坐標位置;sy 可選,開始剪切的 y 坐標位置;swidth 可選,被剪切圖像的寬度;sheight 可選,被剪切圖像的高度;x 表示在畫布上放置圖像的 x 坐標位置;y 在畫布上放置圖像的 y 坐標位置;width 可選,表示要使用的圖像的寬度(伸展或縮小圖像);height 可選,表示要使用的圖像的高度(伸展或縮小圖像)。
**圖像平鋪**
```
createPattern(image,type)
```
參數:
type: no-repeat:不平鋪 ;repeat-x:橫方向平鋪;repeat-y:縱方向平鋪;repeat:全方向平鋪
**2.3 像素處理**
通過`getImageData`方法和`putImageData`方法,可以處理每個像素,進而操作圖像內容。
`getImageData()`方法可以用來讀取Canvas的內容,返回一個對象,包含了每個像素的信息。
```
var imageData = ctx.getImageData(x,y,w,h)
```
參數:x是canvas的X軸坐標,y是canvas的Y軸坐標,w是寬度,h是高度。
getImageData()方法返回一個像素顏色數組(該數組的長度等于圖像的像素寬度*圖像的像素高度*4,每個值的范圍是0-255,可讀寫),imageData的屬性data就是指向它,順序是所取像素范圍的從左到右,從上到下,數組的元素是(所有圖形,包括圖片,和繪制的圖形)每個像素的rgba :
```
[r1,g1,b1,a1,r2,g2,b2,a2...]
```
`putImageData()`方法可將數組內容重新繪制到Canvas上。
```
putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
```
參數:imgData 規定要放回畫布的 ImageData 對象;x 是ImageData 對象左上角的 x 坐標,以像素計;y 是ImageData 對象左上角的 y 坐標,以像素計;dirtyX 可選,水平值(x),以像素計,在畫布上放置圖像的位置;dirtyY 可選,垂直值(y),以像素計,在畫布上放置圖像的位置;dirtyWidth 可選,在畫布上繪制圖像所使用的寬度;dirtyHeight 可選,在畫布上繪制圖像所使用的高度。
當然,我們也可以創建一個空白的ImageData對象。
```
var imgData=context.createImageData(width,height);
```
也可創建與指定的另一個ImageData對象尺寸相同的新ImageData對象(其不會復制圖像數據):
```
var imgData=context.createImageData(imageData);
```
ImageData對象有data屬性,它包含 color/alpha 信息的數組。
**2.4 保存與恢復**
save()方法用于保存上下文環境,restore()方法用于恢復到上一次保存的上下文環境。
**2.5 保存圖像**
我們可以使用toDataURL()方法將Canvas數據重新轉化成圖像文件形式:
```
canvas.toDataURL('image/png')
```
上面的代碼將Canvas數據,轉化成PNG data URI。
**2.6 轉換**
**(1)scale()**
scale() 方法縮放當前繪圖至更大或更小。
```
scale(scalewidth,scaleheight)
```
參數:scalewidth 縮放當前繪圖的寬度;scaleheight 縮放當前繪圖的高度。
注意:如果您對繪圖進行縮放,所有之后的繪圖也會被縮放。定位也會被縮放。如果您 scale(2,2),那么繪圖將定位于距離畫布左上角兩倍遠的位置。
**(2)rotate()**
rotate() 方法旋轉當前的繪圖。
```
rotate(angle)
```
參數:angle 旋轉角度,以弧度計。
注意:旋轉只會影響到旋轉完成后的繪圖。
**(3)translate()**
translate() 方法重新映射畫布上的 (0,0) 位置。
```
translate(x,y)
```
參數:x 添加到水平坐標(x)上的值;y 添加到垂直坐標(y)上的值。
**(4)transform()**
```
transform(a,b,c,d,e,f)
```
參數:a 水平縮放繪圖,b 水平傾斜繪圖,c 垂直傾斜繪圖,d 垂直縮放繪圖,e 水平移動繪圖,f 垂直移動繪圖。
**(5)setTransform()**
setTransform() 方法把當前的變換矩陣重置為單位矩陣,然后以相同的參數運行 transform()。
```
setTransform(a,b,c,d,e,f)
```
參數:a 水平縮放繪圖,b 水平傾斜繪圖,c 垂直傾斜繪圖,d 垂直縮放繪圖,e 水平移動繪圖,f 垂直移動繪圖。
注意:該變換只會影響 setTransform() 方法調用之后的繪圖。
**2.7 動畫**
我們可以使用`setInterval()`和`setTimeout()`來產生動畫效果。
還可以使用`requestAnimationFrame()`來制作動畫。
requestAnimationFrame()函數是全局函數。
考慮兼容,如下:
```
var requestAnimFrame = function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(a) {window.setTimeout(a, 1e3 / 60, (new Date).getTime())};
}();
```
使用方法:
```
function step(){
requestAnimationFrame(step);
}
```
requestAnimationFrame()方法會返回一個requestID,是一個長整型非零值,作為一個唯一的標識符,可將該值作為參數傳遞給window.cancelAnimationFrame()來取消這個函數。
```
cancelAnimationFrame(requestID);
```
兼容性代碼:
```
var cancelAnimFrame = function() {
return window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || function(id) { clearTimeout(id); };
}();
```
- 前言
- JavaScript簡介
- 基本概念
- 語法
- 數據類型
- 運算符
- 表達式
- 語句
- 對象
- 數組
- 函數
- 引用類型(對象)
- Object對象
- Array對象
- Date對象
- RegExp對象
- 基本包裝類型(Boolean、Number、String)
- 單體內置對象(Global、Math)
- console對象
- DOM
- DOM-屬性和CSS
- BOM
- Event 事件
- 正則表達式
- JSON
- AJAX
- 表單和富文本編輯器
- 表單
- 富文本編輯器
- canvas
- 離線應用
- 客戶端存儲(Cookie、Storage、IndexedDB)
- HTML5 API
- Video/Audio
- Geolocation API
- requestAnimationFrame
- File API
- FullScreen API
- IndexedDB
- 檢測設備方向
- Blob
- vibrate
- Luminosity API
- WebRTC
- Page Visibility API
- Performance API
- Web Speech
- Notification
- 面向對象的程序設計
- 概述
- this關鍵字
- 原型鏈
- 作用域
- 常用API合集
- SVG
- 錯誤處理機制
- JavaScript開發技巧合集
- 編程風格
- 垃圾回收機制