#3 圖像變換

本章主要知識(shí)點(diǎn):

  1. save() restore() 保存和恢復(fù)狀態(tài)
  2. translate(x, y), rotate(deg), scale(sx, sy)圖形變換
  3. transform(a, b, c, d, e, f), setTransform(a, b, c, d, e, f) 二維矩陣

圖形變換一般指translate, rotate, scale, transform等方法邀泉,對(duì)圖形進(jìn)行控制匾南。

通常繪制圖形一般會(huì)采用先繪制基本圖形,然后將基本圖形進(jìn)行圖形變換得到自己想要的效果。

1.重構(gòu)

上一章中講到繪制星星的圖形效果(星空效果)葛假,我們可以將其重構(gòu)為,先繪制基本輪廓窟社,然后再進(jìn)行圖形變換操作痊末。

重構(gòu)為:

// 繪制一個(gè)標(biāo)準(zhǔn)的星星
// 小圓半徑是大圓的1/2
function starPath(ctx) {
  ctx.beginPath();
   for (var i = 0; i < 5; i++) {
    ctx.lineTo(
     Math.cos((18 + i * 72 - rotation) / 180 * Math.PI),
     -Math.sin((18 + i * 72 - rotation) / 180 * Math.PI)
    );
   ctx.lineTo(
    Math.cos((54 + i * 72 - rotation) / 180 * Math.PI) * 0.5,
    -Math.sin((54 + i * 72 - rotation) / 180 * Math.PI) * 0.5
   );
  }
  ctx.closePath();
}

function drawStar(ctx, x, y, R, rotation) {
  // 圖形變換操作

  // 繪制基本輪廓
  starPath(ctx); 
}

2.translate, rotate, scale

  • translate(x, y): 移動(dòng)圖形
  • rotate(deg): 旋轉(zhuǎn)多大弧度
  • scale(sx, sy): 縮放,要注意這個(gè)函數(shù)會(huì)產(chǎn)生副作用, 比如比例的平移检眯,或增加描邊的寬度等厘擂,使用時(shí)需要注意

值得注意的是: 圖形變換是疊加的,比如:

// 假設(shè)圖形原坐標(biāo)是(0锰瘸, 0)
ctx.translate(100, 100); // 移動(dòng)到(100刽严, 100)
ctx.fillRect(0, 0, 400, 400); // 繪制一個(gè)矩形

// 再次移動(dòng)
ctx.translate(200, 200);
# 此時(shí)的圖形坐標(biāo)變?yōu)?100+200, 100+200) => (300, 300)
ctx.fillRect(0, 0, 400, 400)

一般我們移動(dòng)繪制之后,再將其坐標(biāo)移回去:

ctx.translate(100, 100); // 移動(dòng)到(100避凝, 100)
ctx.fillRect(0, 0, 400, 400); // 繪制一個(gè)矩形
# 繪制之后移動(dòng)回去
ctx.translate(-100, -100);

// 再次移動(dòng)
ctx.translate(200, 200);
# 因?yàn)樯厦孢M(jìn)行了還原舞萄,此時(shí)的圖形坐標(biāo)為(200, 200)
ctx.fillRect(0, 0, 400, 400)

但是這樣做顯得很繁瑣,因此canvas有保存狀態(tài)管削,再恢復(fù)狀態(tài)的函數(shù)save(), restore()

3.save() | restore()

一般這2個(gè)函數(shù)成對(duì)出現(xiàn)

上面的例子可以寫(xiě)為:

# 先保存之前的狀態(tài)
ctx.save();
ctx.translate(100, 100); // (100, 100)
ctx.fillRect(0, 0, 400, 400);
# 恢復(fù)到保存的狀態(tài)
ctx.restore();

ctx.save();
ctx.translate(200, 200);
ctx.fillRect(0, 0, 400, 400);
ctx.restore()

4.完成星空

可以在1.重構(gòu) 的基礎(chǔ)上利用圖形變換完成星空?qǐng)D:

// 獲取隨機(jī)顏色
function getRandomColor() {
  return '#' + ( '00000' + (Math.random() * 0x10000000<<2) ).toString(16).slice(-6);
}

function drawStar(ctx, x, y, R, rotation) {
  ctx.save();

  // 進(jìn)行圖形變換
  ctx.translate(x, y);
  ctx.rotate(rotation / 180 * Math.PI);
  ctx.scale(R, R);

  // 然后繪制基本的輪廓
  starPath(ctx);

  ctx.fillStyle = getRandomColor();
  ctx.fill();

  ctx.restore();
}


for (var i = 0; i < 100; i++) { 
  var ran = Math.random();
  var x = ran * canvas.width;
  # 這里有個(gè)技巧
  # 想要得到畫(huà)布的65%倒脓,則添加一個(gè)系數(shù)0.65
  var y = ran * canvas.height * 0.65;
  var R = ran * 2 * 10;
  var rotation = ran * 360;

  drawStar(ctx, x, y, R, rotation);
}

tips: 想要得到星星分布在畫(huà)布高度的65%佩谣,則添加一個(gè)系數(shù)0.65

具體效果:圖形變換繪制星空

5.transform 變換矩陣

圖形學(xué)變換矩陣是都頂點(diǎn)坐標(biāo)進(jìn)行重計(jì)算的一種方式把还,對(duì)于二維系統(tǒng),則是 3x3 的矩陣茸俭,對(duì)于三維系統(tǒng)則是 4x4 的矩陣吊履。

對(duì)于3x3 的矩陣:

其中 a, c, b, d 負(fù)責(zé)對(duì)圖形進(jìn)行scale, rotate, 對(duì)稱(chēng),skew 等變換调鬓, a, d負(fù)責(zé)圖形的縮放scale, e, f 負(fù)責(zé)對(duì)圖形進(jìn)行平移(translate)變換艇炎。第3行也可以進(jìn)行其他操作,二維矩陣 詳情腾窝。

對(duì)上圖中的默認(rèn)值情況缀踪,即不進(jìn)行變換時(shí),該矩陣為單位矩陣虹脯。

對(duì)于transform函數(shù):

transform(a, b, c, d, e, f)

所有:

translate(100, 100) =>
transform(1, 0, 0, 1, 100, 100)

# a為-1驴娃, 則產(chǎn)生對(duì)Y軸的鏡像效果
transform(-1, 0, 0, 1, 0, 0)
# 當(dāng)然d的值為負(fù)數(shù),則可以產(chǎn)生對(duì)x軸的鏡像翻轉(zhuǎn)效果


scale(1.5, 1.5) =>
transform(1.5, 0, 0, 1.5, 0, 0)

skew則改變b, c的值 =>
transform(1, 0.2, 0, 1, 0, 0)

setTransform()

同樣循集,transform操作是疊加的唇敞,我們可以使用setTransform來(lái)設(shè)置變換效果,使之前的transform失效:

ctx.save()
ctx.transform(1, 0, 0, 1, 50, 100)
ctx.transform(2, 0, 0, 1.5, 0, 0)

# 使上面的transform失效咒彤,得到新的transform效果
ctx.setTransform(1, 0, 0, 1, 100, 100)

總結(jié)

本章的知識(shí)和css中的基礎(chǔ)知識(shí)類(lèi)似疆柔,學(xué)起來(lái)也比較容易理解,對(duì)于二維矩陣則需要多花功夫去了解镶柱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旷档,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子歇拆,更是在濱河造成了極大的恐慌鞋屈,老刑警劉巖范咨,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異谐区,居然都是意外死亡湖蜕,警方通過(guò)查閱死者的電腦和手機(jī)逻卖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)宋列,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人评也,你說(shuō)我怎么就攤上這事炼杖。” “怎么了盗迟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵坤邪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我罚缕,道長(zhǎng)艇纺,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任邮弹,我火速辦了婚禮黔衡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腌乡。我一直安慰自己盟劫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布与纽。 她就那樣靜靜地躺著侣签,像睡著了一般。 火紅的嫁衣襯著肌膚如雪急迂。 梳的紋絲不亂的頭發(fā)上影所,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音僚碎,去河邊找鬼猴娩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛听盖,可吹牛的內(nèi)容都是我干的胀溺。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼皆看,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼仓坞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起腰吟,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤无埃,失蹤者是張志新(化名)和其女友劉穎徙瓶,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體嫉称,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侦镇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了织阅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壳繁。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖荔棉,靈堂內(nèi)的尸體忽然破棺而出闹炉,到底是詐尸還是另有隱情,我是刑警寧澤润樱,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布渣触,位于F島的核電站,受9級(jí)特大地震影響壹若,放射性物質(zhì)發(fā)生泄漏嗅钻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一店展、第九天 我趴在偏房一處隱蔽的房頂上張望养篓。 院中可真熱鬧,春花似錦壁查、人聲如沸觉至。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)语御。三九已至,卻和暖如春席怪,著一層夾襖步出監(jiān)牢的瞬間应闯,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工挂捻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碉纺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓刻撒,卻偏偏與公主長(zhǎng)得像骨田,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子声怔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • >*很不幸态贤,沒(méi)人能告訴你母體是什么,你只能自己體會(huì)* --駭客帝國(guó) 在第四章“可視效果”中醋火,我們研究了一些增強(qiáng)圖層...
    夜空下最亮的亮點(diǎn)閱讀 1,645評(píng)論 0 2
  • Transform字面上就是變形悠汽,改變的意思箱吕。在CSS3中transform主要包括以下幾種:旋轉(zhuǎn)rotate、扭...
    hzrWeber閱讀 22,113評(píng)論 0 19
  • byzhangxinxufromhttp://www.zhangxinxu.com 本文地址:http://www...
    凌雲(yún)木閱讀 7,136評(píng)論 0 8
  • 看了很多視頻柿冲、文章茬高,最后卻通通忘記了,別人的知識(shí)依舊是別人的假抄,自己卻什么都沒(méi)獲得怎栽。此系列文章旨在加深自己的印象,因...
    DCbryant閱讀 1,854評(píng)論 0 4
  • 之前看到很多關(guān)于小朋友入園年齡的討論慨亲,這個(gè)不能一概而論婚瓜,要因人而異宝鼓。我家寶貝是兩歲八個(gè)月入園的刑棵,今年9月4號(hào)入園的...
    27ebdf2ac0e0閱讀 453評(píng)論 0 0