Canvas(畫布)用於在網頁實時生成圖像,而且能夠操做圖像內容,基本上它是一個能夠用JavaScript操做的位圖(bitmap)。css
<canvas>
網頁元素。<canvas id="myCanvas" width="400" height="200">
你的瀏覽器不支持canvas!
</canvas>
複製代碼
<canvas>
的瀏覽器將會忽略在容器中包含的內容,正常渲染canvas。<canvas>
的瀏覽器會顯示代替內容width
和height
html
屬性設置width/height
時隻影響畫布自己不影畫布內容css
屬性設置width/height
時不但會影響畫布自己的高寬,還會使畫布中的內容等比例縮放(縮放參照於畫布默認的尺寸)<canvas>
元素只是創造了一個固定大小的畫布,要想在它上面去繪製內容,須要用getContext()
方法找到它的渲染上下文。//獲取canvas容器
var canvas = document.getElementById('myCanvas');
//建立一個渲染上下文
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
}
複製代碼
上面代碼中,getContext
方法指定參數2d
,表示該canvas
節點用於生成2D圖案(即平面圖案)。若是參數是webgl
,就表示用於生成3D圖像(即立體圖案),這部分實際上單獨叫作WebGL API。html
canvas
畫布提供了一個用來做圖的平面空間,該空間的每一個點都有本身的座標,x表示橫座標,y表示豎座標。原點(0, 0)位於圖像左上角,x軸的正向是原點向右,y軸的正向是原點向下前端
fillStyle
:設置填充顏色,默認黑色strokeStyle
:設置輪廓顏色,默認黑色lineWidth
:設置線條寬度,屬性值爲任意正整數,默認值是1.0。lineJoin
:控制線條相交的方式(默認是miter
)
round
: 圓角bevel
: 斜角miter
: 直角lineCap
:線段末端的形狀(默認值是 butt
)
butt
:線段末端以方形結束。round
:線段末端以圓形結束square
:線段末端以方形結束,可是增長了一個寬度和線段相同,高度是線段厚度一半的矩形區域save()
時,將樣式容器中的狀態壓棧,保存上下文環境restore()
時,將樣式棧的棧頂狀態彈出到樣式容器中,恢復到上一次保存的上下文環境//用save方法,保存了當前設置
ctx.save();
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
ctx.shadowBlur = 5;
ctx.shadowColor = 'rgba(0,0,0,0.5)';
//繪製了一個有陰影的矩形
ctx.fillStyle = '#CC0000';
ctx.fillRect(10,10,150,100);
//使用restore方法,恢復了保存前的設置
ctx.restore();
//繪製了一個沒有陰影的矩形
ctx.fillStyle = '#000000';
ctx.fillRect(180,10,150,100);
複製代碼
beginPath
時,清空整個路徑容器ctx.save();
//關於樣式的設置
ctx.beginPath();
//關於路徑的設置
ctx.restore();
複製代碼
translate(x, y)
:將canvas座標原點移動到(x,y),translate是累加的rotate(angle)
:圍繞原點旋轉圖像angle弧度(順時針),rotate是累加的scale(x, y)
:縮放圖像;x和y分別是橫軸和縱軸的縮放因子(正值),scale是累加的
//填充矩形(x, y是橫縱座標,原點在canvas的左上角)
ctx.fillRect(x, y, width, height);
//邊框矩形,默認1px 黑色。
ctx.strokeRect(x, y, width, height);
//清除指定的矩形區域,變爲透明
ctx.clearRect(x, y, width, height); //繪製動態效果時,經常使用來清除整個畫布
複製代碼
rect(x, y, width, height)
:繪製矩形路徑//新建路徑,beginPath是繪製新圖形的開始
ctx.beginPath()
//路徑(線)的起點,通常在上面這條命令後執行
ctx.moveTo(x, y)
//線的終點
ctx.lineTo(x, y)
//閉合路徑,不是必須的,若是線的終點跟起點同樣,會自動閉合。
ctx.closePath()
//經過線條繪製輪廓(邊框)
ctx.stroke() //不會自動調用closePath()
//經過路徑填充區域(實心)
ctx.fill() //自動調用closePath()
複製代碼
例:繪製一個三角形web
ctx.beginPath();
ctx.moveTo(75, 50); //路徑起點
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);
ctx.fill(); //自動將路徑閉合,並默認填充黑色。
複製代碼
quadraticCurveTo(cp1x, cp1y, x, y)
:繪製二次貝塞爾曲線,cp1x,cp1y爲一個控制點,起始點爲moveto時指定的點,x,y爲結束點。bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
:繪製三次貝塞爾曲線,cp1x,cp1y爲控制點一,cp2x,cp2y爲控制點二,起始點爲moveto時指定的點,x,y爲結束點。ctx.isPointInPath(x, y)
:判斷在當前路徑中是否包含檢測點
fillText(string, x, y)
:在指定的(x,y)位置填充指定的文本
strokeText(string, x, y)
:在指定的(x,y)位置填充指定的文本// 設置字體,必需要有大小和字體
ctx.font = "Bold 20px Arial";
// 設置對齊方式,可選值包括: left, right center
ctx.textAlign = "left";
// 設置填充顏色
ctx.fillStyle = "#008600";
// 設置字體內容,以及在畫布上的位置
ctx.fillText("Hello!", 10, 50);
// 繪製空心字
ctx.strokeText("Hello!", 10, 100);
複製代碼
measureText()
方法:返回一個TextMetrics 對象,包含關於文本尺寸的信息(例如文本的寬度)//繪製圓形
ctx.arc(x, y, r, start, end, true/false) //(x, y)圓心,r半徑,start和end是開始和結束角度,false表示順時針(默認),true表示逆時針。
//繪製弧線
ctx.arcTo(x1, y1, x2, y2, r); //當前端點、(x1,y1)和(x2,y2)這三個點連成的弧線,r是半徑。
複製代碼
例:繪製實心的圓形算法
ctx.beginPath();
ctx.arc(60, 60, 50, 0, Math.PI*2, true);
ctx.fillStyle = "#000000";
ctx.fill();
複製代碼
例:繪製空心圓形canvas
ctx.beginPath();
ctx.arc(60, 60, 50, 0, Math.PI*2, true);
ctx.lineWidth = 1.0;
ctx.strokeStyle = "#000";
ctx.stroke();
複製代碼
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);
複製代碼
createLinearGradient(x1, y1, x2, y2)
:建立一個canvas漸變(線性漸變)
gradient.addColorStop(position, color)
gradient
:createLinearGradient
的返回值addColorStop
方法接受 2 個參數:
position
參數必須是一個 0.0 與 1.0 之間的數值,表示漸變中顏色所在的相對位置,例如,0.5 表示顏色會出如今正中間。color
參數必須是一個有效的 CSS 顏色值,如 #FFF, rgba(0,0,0,1)等等//建立一個canvas線性漸變,返回`CanvasGradient`對象的實例
var myGradient = ctx.createLinearGradient(0, 0, 0, 160);
myGradient.addColorStop(0, "#BABABA");
myGradient.addColorStop(1, "#636363");
//繪製漸變填充的矩形
ctx.fillStyle = myGradient;
ctx.fillRect(10,10,200,100);
複製代碼
createRadialGradient(x1, y1, r1, x2, y2, r2)
:canvas漸變(徑向漸變)
Canvas API 容許將圖像文件插入畫布,作法是讀取圖片後,使用
drawImage
方法在畫布內進行重繪。api
drawImage(image, x, y, width, height)
image
:圖像文件的DOM元素x
和 y
:繪製該圖像的起始座標width
和 height
:目標寬高var image = new Image();
image.src = 'image.png';
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext('2d').drawImage(image, 0, 0);
// 插入頁面底部
document.body.appendChild(image);
return canvas;
}
複製代碼
createPattern(image, repetition)
image
:圖像源epetition
repeat
repeat-x
repeat-y
no-repeat
通常狀況下,咱們都會將fillstyle
的值設置爲createPattern
返回的對象,只表示在某個特定的區域內顯示重複的圖像。數組
經過
getImageData
方法和putImageData
方法,能夠處理每一個像素,進而操做圖像內容。瀏覽器
ctx.getImageData(sx, sy, sw, sh)
:得到一個包含畫布場景像素數據的ImageData
對象,它表明了畫布區域的對象數據
ImageData
對象中存儲着canvas對象真實的像素數據,它包含如下幾個只讀屬性:
width
:圖片寬度,單位是像素height
:圖片高度,單位是像素data
:Uint8ClampedArray類型的一維數組, 包含着RGBA
格式的整型數據,範圍在0至255之間(包括255)var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
複製代碼
putImageData(myImageData, dx, dy)
:把圖像數據繪製到畫布上context.putImageData(imageData, 0, 0);
複製代碼
假定filter是一個處理像素的函數,那麼整個對Canvas的處理流程,能夠用下面的代碼表示。bash
if (canvas.width > 0 && canvas.height > 0) {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
filter(imageData);
context.putImageData(imageData, 0, 0);
}
複製代碼
ctx.createImageData(width, height)
:建立一個ImageData對象
globalAlpha = value
:設置全局透明度,這個屬性影響到 canvas 裏全部圖形的透明度
globalCompositeOperation
:覆蓋合成(source--->新的圖像(源);destination--->已經繪製過的圖形(目標))
source-over
(默認值):源在上面,新的圖像層級比較高source-in
:只留下源與目標的重疊部分(源的那一部分)source-out
:只留下源超過目標的部分source-atop
:砍掉源溢出的部分destination-over
:目標在上面,舊的圖像層級比較高destination-in
:只留下源與目標的重疊部分(目標的那一部分)destination-out
:只留下目標超過源的部分destination-atop
:砍掉目標溢出的部分注意是canvas元素接口上的方法
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL('image/png');
return image;
}
複製代碼
上面的代碼將Canvas數據,轉化成PNG data URI。
灰度圖(grayscale)就是取紅、綠、藍三個像素值的算術平均值。假定d[i]是像素數組中一個象素的紅色值,則d[i+1]爲綠色值,d[i+2]爲藍色值,d[i+3]就是alpha通道值。轉成灰度的算法,就是將紅、綠、藍三個值相加後除以3,再將結果寫回數組。
grayscale = function (pixels) {
var d = pixels.data;
for (var i = 0; i < d.length; i += 4) {
var r = d[i];
var g = d[i + 1];
var b = d[i + 2];
d[i] = d[i + 1] = d[i + 2] = (r+g+b)/3;
}
return pixels;
};
複製代碼
復古效果(sepia)則是將紅、綠、藍三個像素,分別取這三個值的某種加權平均值,使得圖像有一種古舊的效果。
sepia = function (pixels) {
var d = pixels.data;
for (var i = 0; i < d.length; i += 4) {
var r = d[i];
var g = d[i + 1];
var b = d[i + 2];
d[i] = (r * 0.393)+(g * 0.769)+(b * 0.189); // red
d[i + 1] = (r * 0.349)+(g * 0.686)+(b * 0.168); // green
d[i + 2] = (r * 0.272)+(g * 0.534)+(b * 0.131); // blue
}
return pixels;
};
複製代碼