HTML5(六)——Canvas 高階操作
上一篇文章《HTML5(五)——Canvas API》介紹 canvas 繪製基本圖形,這節開始介紹canvas的高階操作。
一、canvas 轉換
canvas 轉換常用的幾種方法介紹,如下:
方法 |
描述 |
scale() |
縮放當前繪圖至更大或更小。 |
rotate() |
旋轉當前繪圖。 |
translate() |
重新對映畫布上的 (0,0) 位置。 |
transform() |
替換繪圖的當前轉換矩陣。 |
setTransform() |
將當前轉換重置為單位矩陣。然後執行 transform()。 |
1.1 、scale - 縮放
使用語法:scale(x,y)
x:表示水平方向的縮放倍數
y:表示垂直方向的縮放倍數
eg:canvas 繪製的矩形框放大兩倍,程式碼如下:
var canvas = document.getElementById("canvas") var ctx = canvas.getContext("2d") ctx.scale(2,2) ctx.fillStyle="red" ctx.fillRect(0,0,200,200)
1.2、translate - 畫布平移
使用語法:translate(x,y)
x:新增到水平座標上的位置
y:新增到垂直座標上的位置
設定之後開始繪製的圖片位置從(x,y)算起。
eg:繪製兩個一樣的矩形,一個在平移前繪製,一個在平移後繪製,程式碼如下:
var canvas = document.getElementById("canvas") var ctx = canvas.getContext("2d") ctx.fillStyle="red" ctx.fillRect(0,0,200,200) //平移 ctx.translate(200,200) ctx.fillRect(0,0,200,200)
執行結果如圖:
1.3 、rotate- 旋轉
使用語法:rotate(angle)
angle 旋轉弧度,如果想使用角度,可以把角度轉成弧度,公式為:deg * Path.PI/180。
eg:將一個矩形旋轉45度,程式碼如下:
var canvas = document.getElementById("canvas") var ctx = canvas.getContext("2d") //旋轉45度 ctx.rotate(45*Math.PI/180) ctx.fillStyle="red" ctx.fillRect(0,0,200,200)
執行結果如圖:
根據上述結果我們發現旋轉的時候,預設原點是畫布的起始點,我們想要的旋轉是在矩形框中心為原點的旋轉,此時我們需要藉助上translate平移,重置一下原點,修改上述程式碼為:
<canvas width="400" height="400" id="canvas"></canvas> var canvas = document.getElementById("canvas") var ctx = canvas.getContext("2d") ctx.translate(200,200) ctx.rotate(45*Math.PI/180) ctx.translate(-200,-200) ctx.fillStyle="red" ctx.fillRect(100,100,200,200)
執行結果如圖:
1.4、transform - 矩陣變換
使用語法:transform(a,b,c,d,e,f)
- a:水平縮放
- b:水平傾斜
- c:垂直傾斜
- d:垂直縮放
- e:水平移動
- f:垂直移動
transform可以替代前邊平移、縮放、旋轉三者,如下:
// 平移
translate(x,y) <=> transform(1,0,0,1,x,y) <=> transform(0,1,1,0,x,y)
// 縮放
sacle(x,y) <=> transform(x,0,0,y,0,0)
// 旋轉
rotate(angle) <=> transform(Math.cos(angle*Math.PI/180), Math.sin(angel*Math.PI/180), -Math.sin(angle*Math.PI/180), Math.cos(angle*Math.PI/180))
1.5、setTransform - 矩陣變換
setTransform()方法將變換的矩陣進行重置,它把當前的變換矩陣重置為單位矩陣
使用語法:transform(a,b,c,d,e,f)
各引數說明:水平旋轉、水平傾斜、垂直傾斜、垂直縮放、水平移動、垂直移動
setTransform() 方法把當前的變換矩陣重置為單位矩陣,然後以相同的引數執行transform()。
二、canvas 操作圖片
drawImage() 在畫布上繪製圖像、畫布或視訊。也能夠繪製圖片的一部分,增加或減少影象的尺寸。以下是三種常見使用語法:
- 語法1:drawImage( img , x , y )
- 語法2:drawImage( img , x , y , width , height )
- 語法3:drawImage( img , sx , sy , swidth, sheight , x , y , width , height )
上述引數表示的意義如下:
引數 |
描述 |
img |
規定要使用的影象、畫布或視訊。 |
sx |
可選。開始剪下的 x 座標位置。 |
sy |
可選。開始剪下的 y 座標位置。 |
swidth |
可選。被剪下影象的寬度。 |
sheight |
可選。被剪下影象的高度。 |
x |
在畫布上放置影象的 x 座標位置。 |
y |
在畫布上放置影象的 y 座標位置。 |
width |
可選。要使用的影象的寬度。(伸展或縮小影象) |
height |
可選。要使用的影象的高度。(伸展或縮小影象) |
eg:利用語法3,進行繪製圖片的部分內容,實現如下效果:
給上述兔子順便加一個點選螢幕暫停開始功能,完整程式碼如下:
<canvas width="400" height="400" id="canvas"></canvas> <script> var canvas = document.getElementById("canvas") var ctx = canvas.getContext("2d") var img = new Image() let pause = false,frameCounter = 0,i=0; img.src = "./rotate.png" img.onload = function(){ requestAnimationFrame(next) } function next(){ ctx.clearRect(0,0,canvas.width,canvas.height) if(frameCounter%5 == 0){ //frameCounter 控制動畫速度 i++ if(i==11)i=0 } ctx.drawImage(img, 0,i*240,240,240, 0,0,240,240) // 每張圖片寬高都是240,具體引數根據圖片而定 frameCounter ++ if(!pause)requestAnimationFrame(next) } window.onclick = function(){ pause = !pause next() } </script>
eg:使用 canvas 畫布處理視訊,使用定時器繪製視訊的當前幀,連續起來就是一個視訊,需要注意的是必須處理暫停和開始播放兩種操作,具體程式碼如下:
var v=document.getElementById("video1"); var c=document.getElementById("myCanvas"); ctx=c.getContext('2d'); v.addEventListener('play',function() {var i=window.setInterval(function() {ctx.drawImage(v,0,0,270,135)},20);},false); v.addEventListener('pause',function() {window.clearInterval(i);},false); v.addEventListener('ended',function() {clearInterval(i);},false);
三、畫素級操作
常見的畫素級的操作有三種:
- getImageData() - 獲取畫布畫素資料
- createImageData() - 建立新的、空白畫素
- putImageData() - 影象畫素資料放回畫布
3.1、getImageData
使用語法:getImageData( x , y , width , height )
- x:要被提取的影象資料矩形區域的左上角 x 座標。
- y:要被提取的影象資料矩形區域的左上角 y 座標。
- width:被提取的影象資料矩形區域的寬度
- height:被提取的影象資料矩形區域的高度
返回一個 imageData 物件,用來描述 canvas 區域隱含的畫素資料,這個區域通過畫素表示,起點是( x , y ),寬高為 widht 和 height 。
imageData 物件包含三個屬性:
- imageData.height - 畫素描述的矩形實際高度。
- imageData.width - 畫素描述的矩形實際寬度。
- imageData.data - 包含 rgba 順序資料的一個數組,資料使用0-255直接整數表示。
3.2、createImageData
使用語法:
createImageData( width , height )
建立一個空白的 imageData 物件,新物件的預設畫素值 transparent black。對於imageData物件中的每個畫素值,都存在 rgba 這四方面的資訊,即:
- r - 紅色(0-255)
- g - 綠色(0-255)
- b - 藍色(0-255)
- a - alpha(0-255,0是透明,255是完全可見)
新物件預設畫素值為(0,0,0,0)。
eg:如果我們想把 imageData 中一個畫素變為紅色時,可以改變第一和第四位資訊,程式碼如下:
var imageData = ctx.createImageData(100,100) imageData.data[0] = 255 imageData.data[1] = 0 imageData.data[2] = 0 imageData.data[3] = 255
3.1、putImageData
使用語法:
putImageData( imgData , x , y , dirtyX , dirtyY , dirtyWidth ,dirtyHeight );
引數及意義:
引數 |
描述 |
imgData |
規定要放回畫布的 ImageData 物件。 |
x |
ImageData 物件左上角的 x 座標,以畫素計。 |
y |
ImageData 物件左上角的 y 座標,以畫素計。 |
dirtyX |
可選。水平值(x),以畫素計,在畫布上放置影象的位置。 |
dirtyY |
可選。水平值(y),以畫素計,在畫布上放置影象的位置。 |
dirtyWidth |
可選。在畫布上繪製圖像所使用的寬度。 |
dirtyHeight |
可選。在畫布上繪製圖像所使用的高度。 |
通過 getImageData 複製的指定矩形畫素資料,編輯之後,通過 putImageData 方法將影象資料放回畫布上。
eg:新增濾鏡效果:上述兔子是白色的變換成紅色兔子,這時需要把綠色和藍色都設定成0即可,程式碼如下:
<canvas width="400" height="400" id="canvas"></canvas> <script> var canvas = document.getElementById("canvas") var ctx = canvas.getContext("2d") var img = new Image() let w = canvas.width,h = canvas.height; img.src = "./rotate.png" img.onload = function(){ ctx.drawImage(img,0,0,240,240,0,0,240,240) let imageData = ctx.getImageData(0,0,w,h) for(let r=0;r<w;r++){ for(let c=0;c<h;c++){ imageData.data[(r*w+c)*4+2 ] = 0 // 把藍色設定成0 imageData.data[(r*w+c)*4+1] = 0 // 把藍色設定成0 } } ctx.putImageData(imageData,0,0) } </script>