HTML5 Canvas 變形。
9. 變形
9.1 轉換
對 translate 方法輸入位移值。下圖中灰色方塊位於座標(0,0),綠色方塊則是將座標位移到畫布正中。 程式碼如下:var x = 0;
var y = 0;
var rW = 100;
var rH = 100;
//原點在畫布的左上角
context.beginPath();
context.fillStyle = "grey";
context.fillRect(x, y, rW, rH);
//將原點位移到畫布正中
context.beginPath();
context.translate(canvas.width / 2, canvas.height / 2);
context.fillStyle = "green";
context.fillRect(x, y , rW, rH);
9.2 比例縮放
對 scale 方法輸入縮放值達到縮放,值1等於原尺寸不縮放,小於1是縮小,大於1則放大。 程式碼如下:var rW = 100;
var rH = 100;
var x = -rW / 2;
var y = -rH / 2;
context.beginPath();
context.translate(canvas.width / 2, canvas.height / 2);
context.scale(0.2, 2);
context.fillStyle = "gold";
context.fillRect(x, y , rW, rH);
利用scale還能做到鏡像效果,只要輸入的值是負的,圖像就會變成相反。下面做了一個簡單的文字倒影效果。
程式碼如下:
var rW = 100;
var rH = 100;
var x = -rW / 2;
var y = -rH / 2;
var text = "Mirror";
context.translate(canvas.width / 2, canvas.height / 2);
//文字
context.beginPath();
context.font = "50px Tahoma";
context.textAlign = "center";
context.textBaseline = "bottom";
context.fillText(text, 0, 0);
//鏡像
context.beginPath();
context.scale(1, -1);
context.font = "50px Tahoma";
context.fillStyle = "#c0c0c0";
context.textAlign = "center";
context.textBaseline = "bottom";
context.fillText(text, 0, 19);
9.3 旋轉
使用rotate方法並輸入弧度。下圖中,淺藍是不旋轉的原本樣子,深藍則是轉90度。 程式碼如下:var rW = 100;
var rH = 200;
var x = -rW / 2;
var y = -rH / 2;
//轉90度
var radians = Math.PI / 2;
context.translate(canvas.width / 2, canvas.height / 2);
//不旋轉
context.beginPath();
context.fillStyle = "#ADD8E6";
context.fillRect(x, y , rW, rH);
//轉90度
context.beginPath();
context.rotate(radians);
context.fillStyle = "#357EC7";
context.fillRect(x, y , rW, rH);
9.4 扭曲
這裡必須利用數學矩陣,我們只要知道幾個矩陣中的值的涵意,就能夠使用了。 這張圖的原圖是從 wiki 的Transformation matrix找來的,我加了下面的紅字部份,只要知道這6個位置的涵意即可做到自訂變形。這6個數字會輸入 transfrom 方法中。context.transform(a, b, c, d, e, f);下圖中,灰色方塊為原圖,紅色方塊的起點位移到畫布正中,綠色方塊則以紅色方塊的座標為原點做水平位移,並且做Y軸的傾斜。 程式碼如下:
var rW = 50;
var rH = 50;
var x = 0;
var y = 0;
//(灰)原圖
context.beginPath();
context.fillStyle = "#808080";
context.fillRect(x, y , rW, rH);
//(紅)改變tx,ty的做法如同translate方法
var tx = canvas.width / 2;
var ty = canvas.height / 2;
context.beginPath();
context.transform(1, 0, 0 , 1, tx, ty);
context.fillStyle = "#A52A2A";
context.fillRect(x, y, rW, rH);
//(綠)對y軸做傾斜
tx = 60;
ty = 0;
var sx = 0;
var sy = 0.5;
context.beginPath();
context.transform(1, sy, sx , 1, tx, ty);
context.fillStyle = "#008000";
context.fillRect(x, y, rW, rH);
這個範例中,綠色方塊的座標受到紅色方塊使用transform的影響,所以出現在紅色方塊旁邊,我們可以使用setTransform方法把轉變效果歸零,讓下一個物件不會受到上一個物件變形的影響。只要在下一個物件之前使用
context.setTransform(1, 0, 0, 1, 0, 0);
就會把變形效果歸回原值。觀察之前的那個矩陣公式就可瞭解。
9.5 狀態的儲存及恢復
變形的效果可以儲存成狀態,之後可以恢復成該狀態。狀態的儲存方式採用堆疊的方式,也就是最先儲存的,最後才能取回。儲存狀態使用save方法,恢復狀態則使用restore方法。下圖中,依序儲存了3個狀態,紅色方塊套用到全部的變形;藍色則因為恢復到前一狀態,而少了旋轉;綠色方塊則又少了放大效果;黃色方塊則是最原始的狀態無任何效果。 程式碼如下:
var rW = 50;
var rH = 50;
var x = 0;
var y = 0;
var radians = Math.PI / 4;
//儲存狀態:1 - 無任何效果
context.save();
//儲存狀態:2 - 位移
context.translate(x+71, y);
context.save();
//儲存狀態:3 - 放大
context.scale(2, 2);
context.save();
//旋轉
context.rotate(radians);
//(紅)套用效果:位移,放大,旋轉
context.fillStyle = "red";
context.fillRect(x, y, rW, rH);
//恢復到最後一次的狀態:3
//(藍)套用效果:位移,放大
context.restore();
context.fillStyle = "blue";
context.fillRect(x, y, rW, rH);
//恢復到最後一次的狀態:2
//(綠)套用效果:位移
context.restore();
context.fillStyle = "green";
context.fillRect(x, y, rW, rH);
//恢復到最後一次的狀態:1
//(綠)套用效果:無任何效果
context.restore();
context.fillStyle = "gold";
context.fillRect(x, y, rW, rH);
9.2 比例縮放
回覆刪除裡面有提到scale是負值就可以做出鏡像效果
但是我用負值之後他卻無法顯示
求解
你調一下"鏡像"部份的fillText()的座標值,它有可能跑到 canvas 外面了。
刪除我把程式碼貼在這(https://jsfiddle.net/f2r07ch4/1/#&togetherjs=r1HQDwFgmV)你可以玩玩看