Canvas教程(16)——矩陣變換

變換矩陣

之前三節(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)變換

旋轉(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)替代茸炒。


以上結(jié)論引自張?chǎng)┑牟┛?/a>愕乎,很好的說(shuō)明了矩陣變換的過(guò)程阵苇,但是結(jié)論過(guò)于復(fù)雜,建議使用transform()的時(shí)候感论,可以在如下幾個(gè)情況下使用:

  1. 使用context.transform (1,0,0,1,dx,dy)代替context.translate(dx,dy)
  2. 使用context.transform(sx,0,0,sy,0,0)代替context.scale(sx, sy)
  3. 使用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>

演示 16-1

運(yùn)行結(jié)果:

transform

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>

演示 16-2

運(yùn)行結(jié)果:

setTransform

解釋一下過(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

Canvas--Draw on the Web
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市逛球,隨后出現(xiàn)的幾起案子千元,更是在濱河造成了極大的恐慌,老刑警劉巖颤绕,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幸海,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡奥务,警方通過(guò)查閱死者的電腦和手機(jī)物独,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)氯葬,“玉大人挡篓,你說(shuō)我怎么就攤上這事。” “怎么了官研?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵秽澳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我戏羽,道長(zhǎng)担神,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任始花,我火速辦了婚禮妄讯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘酷宵。我一直安慰自己捞挥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布忧吟。 她就那樣靜靜地躺著砌函,像睡著了一般。 火紅的嫁衣襯著肌膚如雪溜族。 梳的紋絲不亂的頭發(fā)上讹俊,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音煌抒,去河邊找鬼仍劈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛寡壮,可吹牛的內(nèi)容都是我干的贩疙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼况既,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼这溅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起棒仍,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤悲靴,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后莫其,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體癞尚,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年乱陡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浇揩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡憨颠,死狀恐怖胳徽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤膜廊,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布乏沸,位于F島的核電站,受9級(jí)特大地震影響爪瓜,放射性物質(zhì)發(fā)生泄漏蹬跃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一铆铆、第九天 我趴在偏房一處隱蔽的房頂上張望蝶缀。 院中可真熱鬧,春花似錦薄货、人聲如沸翁都。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)柄慰。三九已至,卻和暖如春税娜,著一層夾襖步出監(jiān)牢的瞬間坐搔,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工敬矩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留概行,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓弧岳,卻偏偏與公主長(zhǎng)得像凳忙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子禽炬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容