變換矩陣
之前三節(jié)所說(shuō)的坐標(biāo)變換的三種方式——平移translate()
,縮放scale()
,以及旋轉(zhuǎn)rotate()
都可以通過(guò)transform()
做到泵三。
在介紹矩陣變換transform()
前遂跟,我們來(lái)說(shuō)一說(shuō)什么是變換矩陣。
以上是Canvas中transform()
方法所對(duì)應(yīng)的變換矩陣透揣。而此方法正是傳入圖中所示的六個(gè)參數(shù)济炎,具體為context.transform(a,b,c,d,e,f)
。
各參數(shù)意義對(duì)應(yīng)如下表:
參數(shù) | 意義 |
---|---|
a | 水平縮放(1) |
b | 水平傾斜(0) |
c | 垂直傾斜(0) |
d | 垂直縮放(1) |
e | 水平位移(0) |
f | 垂直位移(0) |
當(dāng)我們把對(duì)應(yīng)的0或1代入進(jìn)矩陣辐真,可以發(fā)現(xiàn)這是一個(gè)單位矩陣(水平和垂直縮放默認(rèn)值是1须尚,代表縮放1倍,即不縮放)侍咱。該方法使用一個(gè)新的變化矩陣與當(dāng)前變換矩陣進(jìn)行乘法運(yùn)算耐床,然后得到各種變化的效果。
這里簡(jiǎn)單說(shuō)一下楔脯,當(dāng)我們想對(duì)一個(gè)圖形進(jìn)行變換的時(shí)候撩轰,只要對(duì)變換矩陣相應(yīng)的參數(shù)進(jìn)行操作,操作之后淤年,對(duì)圖形的各個(gè)定點(diǎn)的坐標(biāo)分別乘以這個(gè)矩陣钧敞,就能得到新的定點(diǎn)的坐標(biāo)蜡豹。
而Canvas繪圖中麸粮,就給咱們提供了一個(gè)函數(shù)來(lái)改變這個(gè)變換矩陣,那就是transform()
镜廉。
矩陣變換transform()
注:以下三個(gè)變換的轉(zhuǎn)換結(jié)論轉(zhuǎn)自張?chǎng)┑牟┛?/a>弄诲,童鞋們可以戳進(jìn)去看看詳情。
平移變換
如上圖所示:
x’ = x + dx
娇唯,
y’ = y + dy
齐遵。
也即是說(shuō)可以使用
context.transform (1,0,0,1,dx,dy)
代替context.translate(dx,dy)
。
也可以使用
context.transform(0,1,1,0,dx,dy)
代替塔插。
縮放變換
同理可以使用
context.transform(sx,0,0,sy,0,0)
代替context.scale(sx, sy)
;
也可以使用context.transform(0,sy,sx,0,0,0)
;
旋轉(zhuǎn)變換
如上圖圖所示:
B點(diǎn)是通過(guò)A點(diǎn)逆時(shí)針旋轉(zhuǎn)θ得到梗摇,
x = r * cosa
,
y = r * sina
即
x’=r*cos(a+θ)=x*cosθ-y*sinθ
想许,
y’=r*sin(a+θ)=x*sinθ+y*cosθ
也即是
綜上:
context.transform(Math.cos(θ*Math.PI/180)伶授,Math.sin(θ*Math.PI/180), -Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),0流纹,0)
可以替代context.rotate(θ)
糜烹。
也可以使用
context.transform(-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180), Math.cos(θ*Math.PI/180)漱凝,Math.sin(θ*Math.PI/180)疮蹦,0,0)
替代茸炒。
- 使用
context.transform (1,0,0,1,dx,dy)
代替context.translate(dx,dy)
- 使用
context.transform(sx,0,0,sy,0,0)
代替context.scale(sx, sy)
- 使用
context.transform(0,b,c,0,0,0)
來(lái)實(shí)現(xiàn)傾斜效果(最實(shí)用)慎玖。
不用再使用它去實(shí)現(xiàn)旋轉(zhuǎn)了,另外也沒(méi)有也不用全記這些結(jié)論笛粘,直接記下abcdef六個(gè)參數(shù)的意義趁怔,效果是一樣的。
下面我們看一個(gè)代碼薪前,熟悉一下:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>矩陣變換</title>
<style>
body { background: url("./images/bg3.jpg") repeat; }
#canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }
</style>
</head>
<body>
<div id="canvas-warp">
<canvas id="canvas">
你的瀏覽器居然不支持Canvas润努?!趕快換一個(gè)吧J纠ā铺浇!
</canvas>
</div>
<script>
window.onload = function(){
var canvas = document.getElementById("canvas");
canvas.width = 800;
canvas.height = 600;
var context = canvas.getContext("2d");
context.fillStyle = "#FFF";
context.fillRect(0,0,800,600);
context.fillStyle = "yellow";
context.strokeStyle = "#00AAAA";
context.lineWidth = 5;
context.save();
//平移至(300,200)
context.transform(1,0,0,1,300,200);
//水平方向放大2倍,垂直方向放大1.5倍
context.transform(2,0,0,1.5,0,0);
//水平方向向右傾斜寬度10%的距離垛膝,垂直方向向上傾斜高度10%的距離
context.transform(1,-0.1,0.1,1,0,0);
context.fillRect(0,0,200,200);
context.strokeRect(0,0,200,200);
context.restore();
};
</script>
</body>
</html>
運(yùn)行結(jié)果:
setTransform()
方法
transform()
方法的行為相對(duì)于由 rotate()
,scale()
, translate()
, or transform()
完成的其他變換鳍侣。例如:如果我們已經(jīng)將繪圖設(shè)置為放到兩倍,則 transform()
方法會(huì)把繪圖放大兩倍吼拥,那么我們的繪圖最終將放大四倍倚聚。這一點(diǎn)和之前的變換是一樣的。
但是setTransform()
不會(huì)相對(duì)于其他變換來(lái)發(fā)生行為凿可。它的參數(shù)也是六個(gè)惑折,context.setTransform(a,b,c,d,e,f)
,與transform()
一樣枯跑。
這里我們通過(guò)一個(gè)例子來(lái)說(shuō)明:
繪制一個(gè)矩形惨驶,通過(guò) setTransform()
重置并創(chuàng)建新的變換矩陣,再次繪制矩形敛助,重置并創(chuàng)建新的變換矩陣粗卜,然后再次繪制矩形。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>矩陣變換</title>
<style>
body { background: url("./images/bg3.jpg") repeat; }
#canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }
</style>
</head>
<body>
<div id="canvas-warp">
<canvas id="canvas">
你的瀏覽器居然不支持Canvas纳击?续扔!趕快換一個(gè)吧!评疗!
</canvas>
</div>
<script>
window.onload = function(){
var canvas = document.getElementById("canvas");
canvas.width = 800;
canvas.height = 600;
var context = canvas.getContext("2d");
context.fillStyle = "#FFF";
context.fillRect(0,0,800,600);
context.fillStyle="yellow";
context.fillRect(200,100,250,100)
context.setTransform(1,0.5,-0.5,1,30,10);
context.fillStyle="red";
context.fillRect(200,100,250,100);
context.setTransform(1,0.5,-0.5,1,30,10);
context.fillStyle="blue";
context.fillRect(200,100,250,100);
};
</script>
</body>
</html>
運(yùn)行結(jié)果:
解釋一下過(guò)程:每當(dāng)我們調(diào)用 setTransform()
時(shí)测砂,它都會(huì)重置前一個(gè)變換矩陣然后構(gòu)建新的矩陣,因此在下面的例子中百匆,不會(huì)顯示紅色矩形砌些,因?yàn)樗谒{(lán)色矩形下面。
這一節(jié)的內(nèi)容有些難和多,但是除了傾斜其他并不實(shí)用存璃,所以童鞋們盡量了解一下就好仑荐,能夠掌握就更好啦!至此纵东,所有的圖形變換我們已經(jīng)上完了粘招,基本的三大變化——平移變換、旋轉(zhuǎn)變換偎球、縮放變換洒扎,以及萬(wàn)能的矩陣變換。大家都以及完全掌握了嗎衰絮?如果不熟練袍冷,要回頭多看看,并且多加練習(xí)猫牡。稍作休息胡诗,下一節(jié)開(kāi)始,就是新的航程淌友!我們繼續(xù)前進(jìn)煌恢!??
如果您喜歡本書(shū),請(qǐng)使用支付寶掃描下面的二維碼捐助作者震庭。
謝謝您的支持瑰抵!也歡迎您訂閱本書(shū)。
如果書(shū)中有疏漏或錯(cuò)誤之處归薛,敬請(qǐng)您指出谍憔,期待您的pull request。如果有任何疑問(wèn)也可以發(fā)送issue主籍。
本人郵箱:airing@ursb.me
本人博客:http://ursb.me
本書(shū)地址:http://airingursb.gitbooks.io/canvas
本書(shū)github:http://github.com/airingursb/canvas