Canvas是HTML5中一個重要的組件,提供了一系列接口使得可以開發者可以利用Js繪製各種圖表、動畫。
Canvas瀏覽器檢測
如果你的代碼需要兼容舊的瀏覽器,則可以如下代碼來檢測:
const canvas = document.querySelector("#canvas");
if (canvas.getContext) {
// do something
} else {
// fallback
}
或者使用Modernizr庫來識別瀏覽器是否支持Canvas:
if (Modernizr.canvas) {
// canvas code
} else {
// fallback code
}
不過對於大家常用的現代瀏覽器來說,Canvas已經算是標配了。所以上述代碼加不加其實主要看產品的需求。
Canvas 特點
Canvas提供了一系列繪圖接口,且都是基於像素的,所以我們可以利用Canvas實現很多有趣的功能,比如截圖、圖片渲染等。常用的接口主要有畫圖片,文本,線條以及gradients等,Canvas還支持和CSS3 的transform類似的變換操作,不過不支持動畫(animation)。
我們在使用canvas時,主要有以下幾個步驟:
- 定義一個canvas元素
- 設置canvas的一些屬性(如寬高等)
- 獲得2d context上下文對象
- 畫圖
例子如下:
const canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
const context = canvas.getContext("2d");
context.fillRect(0, 0, 20, 20);
document.body.appendChild(canvas);
基礎知識
在Canvas中,畫布的座標空間是從左上角開始的:
[圖片上傳失敗...(image-44c488-1578909996036)]
所有繪製的元素都會基於原點進行定位,不過canvas中也提供了接口來變換原點位置。
矩形和橢圓
在canvas中如果你想要畫矩形的話,主要有以下3個方法:
- clearRect(x, y, width, height): 清除指定矩形區域
- fillRect(x, y, width, height): 繪製填充的矩形
- strokeRect(x, y, w, h): 繪製一個矩形邊框
對於畫布上下文的設置,主要利用fillStyle
和strokeStyle
兩個屬性設置顏色等樣式。
const canvas = document.querySelector("#mycanvas");
const ctx = canvas.getContext("2d");
ctx.fillRect(20, 20, 100, 200); // 繪製一個寬100,高100的矩形
而要畫一個橢圓的話,主要藉助兩個接口:
- arc(x, y, radius, startAngle, endAngle, antiClockwise): 畫一個以(x, y)爲圓心,radius爲半徑的圓弧,從startAngle開始到endAngle結束,antiClosewise爲繪製方向,默認是順時針
- arcTo(x1, y1, x2, y2, radius): 根據(x1, y1)和(x2, y2),已經半徑來繪製圓弧,再以直線連接兩個控制點
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.arc(50, 50, 10, 0, Math.PI * 0.5, false);
ctx.fill();
線段和路徑
- 首先,你需要創建路徑起始點。
- 然後你使用畫圖命令去畫出路徑。
- 之後你把路徑封閉。
- 一旦路徑生成,你就能通過描邊或填充路徑區域來渲染圖形。
- beginPath(): 新建路徑,生成之後,圖形繪製命令被指向到路徑上生成路徑
- bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y): 三次貝塞爾曲線,(cp1x,cp1y)爲控制點一,(cp2x,cp2y)爲控制點二,(x,y)爲結束點
- closePath(): 閉合路徑
- moveTo(x, y): 移動到某個點,以這個點爲基礎來繪製圖形
- quadraticCurveTo(cpx, cpy, x, y): 二次貝塞爾曲線,(cpx,cpy)爲一個控制點,(x,y)爲結束點
- stroke(): 繪製輪廓
- fill(): 填充路徑內容區域
主要使用的屬性有:
lineCap, lineJoin, lineWidth, miterLimit
以下是例子:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 繪製一個三角形
ctx.beginPath(); // 生成路徑
ctx.moveTo(75, 50); // 以 (75, 50)這個座標爲起點開始繪製
ctx.lineTo(100, 75); // 移動到(100,75)這個座標畫一條線
ctx.lineTo(100, 25); // 再移動到 (100, 25)這個座標畫一條線
ctx.fill(); // 填充圖形,沒有閉合的圖形會自動閉合,所以無需調用closePath接口
文本
繪製文本我們主要用以下兩種接口:
- fillText(text, x, y, [maxWidth]): 在x, y處繪製指定文本,可以選擇最大寬度
- strokeText(text, x, y, [maxWidth]): 在x, y處繪製指定文本的邊框,可以選擇最大寬度
ctx.font = "16px serif";
ctx.strokeText("Hello", 50, 50);
圖片
圖片繪製也是canvas中常用的功能,可以使用如下接口來實現:
- drawImage(image, x, y, [width], [height]): 其中
image
是 image 或者 canvas 對象,(x,y)爲繪製的起點
const image = new Image();
image.onload(function() {
ctx.drawImage(image, 0, 0, 100, 100);
});
image.src = "http://xxxx";
動畫
可以利用canvas繪製動畫,一個動畫由很多幀組成,每一幀都需要以下這些步驟:
- 清空canvas
- 保存canvas
- 繪製圖形
- 恢復canvas
然後可以使用requestAnimationFrame來執行一個動畫,對於舊的瀏覽器則使用setInterval來調用回調函數。
例子可以參考: https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Basic_animations
Path2D
Path2D 是一個比較新的對象,利用它可以緩存和記錄已有的路徑信息,以便在後續複用。
主要有以下三種方式新建一個Path2D對象:
- new Path(): 空的path對象
- new Path2D(path): 克隆一個新的Path對象
- new Path2D(d): 從SVG建立Path對象, d 爲svg路徑字符串如: "M10 10 h 80 v 80 h -80 Z"
const ctx = canvas.getContext('2d');
var rectangle = new Path2D();
rectangle.rect(10, 10, 50, 50);
var circle = new Path2D();
circle.moveTo(125, 35);
circle.arc(100, 35, 25, 0, 2 * Math.PI);
ctx.stroke(rectangle);
ctx.fill(circle);
接口
最後來列舉一下Canvasa中所有常見的接口以及對應的功能,在忘記的時候能夠快速索引到:
接口 | 功能描述 |
---|---|
addColorStop | 繪製過渡效果是添加結束點的顏色 |
drawImage | 繪製圖片 |
restore | 從棧中恢復上下文 |
arc | 繪製弧線 |
fill | 填充 |
rotate(angle) | 以原點爲中心旋轉canvas |
arcTo | 繪製圓弧 |
fillRect | 填充矩形 |
save | 將上下文保存到棧中 |
beginPath | 開始路徑 |
fillText | 填充文本 |
scale(x, y) | 縮放畫布 |
bezierCurveTo | 曲線 |
getImageData | 獲得圖片數據 |
setTransform(m11, m12, m21, m22, dx, dy) | 設置變換矩陣 |
clearRect | 清楚矩形區域 |
isPointInPath | 判斷像素點是否在對應的路徑上 |
stroke | 繪製輪廓 |
clip | 裁剪 |
lineTo | 繪製直線 |
strokeRect | 繪製矩形輪廓 |
closePath | 關閉路徑 |
measureText | 返回一個包含指定文本寬度的對象(以像素爲單位) |
strokeText | 繪製文本輪廓 |
createImageData | 創建圖片像素數據 |
moveTo | 移動到某點,並以這個點爲基礎繪製圖形 |
transform(m11, m12, m21, m22, dx, dy) | 使用變換矩陣 |
createLinearGradient | 創建一個線性過渡對象 |
putImageData | 將圖像數據放回畫布 |
translate | 移動canvas和原點到(x,y)上 |
createPattern | 圖像填充,在指定的方向內重複指定的元素 |
quadraticCurveTo | 二次貝塞爾曲線 |
createRadialGradient | 創建一條放射顏色漸變 |
rect | 創建矩形 |
API 屬性有:
屬性 | 描述 |
---|---|
data |
Uint8ClampedArray 類型的一維數組,包含着RGBA格式的整型數據,範圍在0至255之間(包括255),ImageData對象的屬性 |
miterLimit |
miterLimit 屬性就是用來設定外延交點與連接點的最大距離,如果交點距離大於此值,連接效果會變成了 bevel。 |
fillStyle | 填充顏色 |
shadowBlur | 陰影的模糊程度,默認爲0 |
font | 繪製文本時的字體,默認的字體是 10px sans-serif
|
shadowColor | 陰影顏色,默認是全透明的黑色 |
globalAlpha | 透明度,從0.0 到 1.0 |
globalCompositeOperation | 在畫新圖形時採用的遮蓋策略,其值是一個標識12種遮蓋方式的字符串,參考 |
lineCap | 線條末端樣式,butt , round 和 square, 默認值是 butt` |
lineJoin | 線條與線條間接合處的樣式,有3個值:round , bevel 和miter
|
lineWidth | 線條寬度 |
shadowOffsetX | 用來設定陰影在X軸的延伸距離 |
shadowOffsetY | 用來設定陰影在Y 軸的延伸距離 |
strokeStyle | 圖形輪廓顏色 |
textAlign | 繪製文本的對齊選項,可選的值包括:start , end , left , right or center . 默認值是 start
|
textBaseline | 繪製文本時的基線對齊選項. 可選的值包括:top , hanging , middle , alphabetic , ideographic , bottom 。默認值是 alphabetic。
|
direction | 繪製文本的方向,可能的值包括:ltr , rtl , inherit 。默認值是 inherit
|
參考資料
https://html.spec.whatwg.org/multipage/canvas.html
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes