transform和CATransform3D


UIView的transform屬性是CGAffineTransform類型函似,用于在二維空間做旋轉(zhuǎn)槐脏,縮放和平移。
CGAffineTransform是一個可以和二維空間向量做乘法的3 * 2矩陣撇寞。如下圖:


仿射變換
當(dāng)對圖層應(yīng)用變換矩陣顿天,圖層矩形內(nèi)的每一個點都被相應(yīng)的做變換堂氯,從而形成一個新的形狀。CGAffineTransform仿射變換的仿射意思是無論變換矩陣用什么值牌废,圖層中平行的兩條線在變換之后仍然保持平行咽白。
看了上邊的一些概念,可能覺得霧里云里鸟缕,不如我們直接上代碼和效果晶框。
CGAffineTransform是CG開頭的,也就是說是在Core Graphics框架里的懂从,這個框架為我們提供了好用的函數(shù)可以讓我們不必自己去親自計算矩陣的相乘授段。

//常用的三個函數(shù):
CGAffineTransformMakeRotation(CGFloat angle) 
// 旋轉(zhuǎn) 表示旋轉(zhuǎn)多少角度,如果是正數(shù)的番甩,會按照順時針旋轉(zhuǎn)侵贵,如果負(fù)數(shù),則逆時針旋轉(zhuǎn)缘薛。
//注意窍育,這個函數(shù)傳入的參數(shù)不是我們平常說的角度而是弧度。如果覺得分不清楚宴胧,或總是混淆的話漱抓,可以用下邊給出的兩個宏做計算。
CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
 // 縮放 兩個參數(shù)分別表示水平方向(x軸)和豎直方向(y軸)的縮放比例恕齐。
CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)  
// 平移 兩個參數(shù)分別表示水平方向(x軸)和豎直方向(y軸)上平移的位移(以點`point`計)
//弧度轉(zhuǎn)角度
#define RADIANS_TO_DEGREES(x) ((x)/M_PI*180.0)//傳入弧度 eg: M_PI_4
//角度轉(zhuǎn)弧度
#define DEGREES_TO_RADIANS(x) ((x)/180.0*M_PI)//傳入度數(shù)eg:45度
- (void)test0
{
    ///右轉(zhuǎn)90度
    CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_2);
    
    //以下兩個賦值效果一樣乞娄。最終都是作用于layer上。
    self.label.transform = transform;
//    self.label.layer.affineTransform = transform;
}

- (void)test1
{
    //水平方向縮小0.5倍显歧,豎直方向縮小0.8倍
    CGAffineTransform transform = CGAffineTransformMakeScale(0.5, 0.8);
    self.label.layer.affineTransform = transform;
}

- (void)test2
{
    //水平方向上平移20补胚;豎直方向平移10
    CGAffineTransform transform = CGAffineTransformMakeTranslation(20, 10);
    self.label.layer.affineTransform = transform;
}

圖中藍(lán)色視圖是紅色視圖的父視圖,作為初始狀態(tài)和形變后的樣子做對比追迟。第一張是選擇溶其,第二種是縮放,第三張是平移敦间。


混合變換
如果想讓一個view既縮放又旋轉(zhuǎn)瓶逃,就用到混合變換了。Core Graphics也給我們提供了方便好用的接口廓块。

/*
 CGAffineTransformIdentity: //單位矩陣

 “CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
 CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
 CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)”
 //兩個變換的基礎(chǔ)上生成另一個變換
 “CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);”
 */

@property(nonatomic) CGAffineTransform transform; // default is CGAffineTransformIdentity. animatable
//UIView的transform的屬性的默認(rèn)值就是CGAffineTransformIdentity厢绝。
調(diào)用這些函數(shù)要傳入一個初始值,即CGAffineTransformIdentity带猴,這個是CGAffineTransform類型的空值昔汉。也是UIView的transform屬性的默認(rèn)值。以上幾個函數(shù)拴清,可以將不同的效果疊加靶病。

- (void)mixTest0
{
    CGAffineTransform transfrom = CGAffineTransformIdentity;
    transfrom = CGAffineTransformRotate(transfrom,DEGREES_TO_RADIANS(60));//旋轉(zhuǎn)60度
    transfrom = CGAffineTransformScale(transfrom, 0.5, 0.6);
    transfrom = CGAffineTransformTranslate(transfrom, 0, 50);
//沒有垂直向下移動50会通,因為會疊加上兩個形變的結(jié)果,相當(dāng)于向斜下方移動了50 * 0.6
    self.label.layer.affineTransform = transfrom;
    //“后邊的形變會作用在之前形變的結(jié)果之上,也就是說旋轉(zhuǎn)之后的平移和平移之后的旋轉(zhuǎn)結(jié)果可能不同娄周。
}

  • 3D變換
    上邊說的仿射變換和混合變換都是在平面上的效果承二,圖層layer的transform屬性(CATransform3D類型 )可以讓圖層在3D空間內(nèi)移動或者旋轉(zhuǎn)笛臣。CATransform3D是在3維空間內(nèi)做變換的4 * 4的矩陣。
//3D的變換比仿射變換多了一個角度和一個z軸的參數(shù)克婶。
//CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z)
//CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz) 
//CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)”

下圖是3D空間內(nèi)鸵荠,針對x,y,z軸以及其旋轉(zhuǎn)方向稠鼻。


- (void)test3D_x
{
//在豎直方向壓縮了 實際是沿著豎直方向傾斜了45度去看  如果是90度則完全看不到
    CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 1, 0, 0);
    self.label.layer.transform = transform;
}

- (void)test3D_y
{
//效果是在水平方向壓縮了  實際是沿著水平方向傾斜了45度去看 如果是90度則完全看不到
    CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
    self.label.layer.transform = transform;
}
- (void)test3D_z//效果是在正對著用戶的方向上旋轉(zhuǎn)了45度
{
    CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
    self.label.layer.transform = transform;
}


其實單直接對以上函數(shù)的參數(shù)做變動商佑,看不出太多效果耕挨,和自己想象中的3D效果不一樣【槌梗看著好像是圖層進(jìn)行了壓縮技肩,其實是因為相當(dāng)于我們換個角度去看圖層導(dǎo)致。
要想達(dá)到透視效果浮声,我們需要對CATransform3D這個矩陣做操作。


  • 透視
    我們不需要去管矩陣計算怎么復(fù)雜旋奢,我們只要控制一個矩陣中m34的值就可以泳挥。m34用于按比例縮放X和Y的值來計算到底要離視角有多遠(yuǎn)。所以我們可以用CATransform3Dm34的值用來做透視至朗。
    m34的值默認(rèn)是0屉符,可以通過設(shè)置m34-1.0 / d來實現(xiàn)透視效果,d的取值范圍500~1000锹引。
- (void)testPerspective_x
{
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = - 1.0 / 500;
    transform = CATransform3DRotate(transform, M_PI_4, 1, 0, 0);
    self.label.layer.transform = transform;
}

- (void)testPerspective_y
{
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = - 1.0 / 500;
    transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);
    self.label.layer.transform = transform;
}

- (void)testPerspective_z
{
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = - 1.0 / 500;
    transform = CATransform3DRotate(transform, M_PI_4, 0, 0, 1);
    self.label.layer.transform = transform;
}


結(jié)果如上圖矗钟,我們設(shè)置了m34的值后,看著才有了3D的效果嫌变。具體你效果需要什么樣吨艇,可以根據(jù)自己的需要進(jìn)行設(shè)置。
總結(jié):
變換這塊自己平常不怎么用到腾啥,偶爾需要用到的時候也總想不起來东涡,在這里總結(jié)一下,以后便于查找學(xué)習(xí)倘待。希望對看到的讀者也有所幫助疮跑。感謝下邊書籍的翻譯者,感謝凸舵。配套Demo可供參考祖娘。
參考書籍:ios核心動畫高級技巧

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市啊奄,隨后出現(xiàn)的幾起案子渐苏,更是在濱河造成了極大的恐慌掀潮,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件整以,死亡現(xiàn)場離奇詭異胧辽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)公黑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門邑商,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凡蚜,你說我怎么就攤上這事人断。” “怎么了朝蜘?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵恶迈,是天一觀的道長。 經(jīng)常有香客問我谱醇,道長暇仲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任副渴,我火速辦了婚禮奈附,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘煮剧。我一直安慰自己斥滤,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布勉盅。 她就那樣靜靜地躺著佑颇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪草娜。 梳的紋絲不亂的頭發(fā)上挑胸,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機(jī)與錄音宰闰,去河邊找鬼嗜暴。 笑死,一個胖子當(dāng)著我的面吹牛议蟆,可吹牛的內(nèi)容都是我干的闷沥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼咐容,長吁一口氣:“原來是場噩夢啊……” “哼舆逃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤路狮,失蹤者是張志新(化名)和其女友劉穎虫啥,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奄妨,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡涂籽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了砸抛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片评雌。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖直焙,靈堂內(nèi)的尸體忽然破棺而出景东,到底是詐尸還是另有隱情,我是刑警寧澤奔誓,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布斤吐,位于F島的核電站,受9級特大地震影響厨喂,放射性物質(zhì)發(fā)生泄漏和措。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一蜕煌、第九天 我趴在偏房一處隱蔽的房頂上張望派阱。 院中可真熱鬧,春花似錦幌绍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至彩届,卻和暖如春伪冰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背樟蠕。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工贮聂, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寨辩。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓吓懈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親靡狞。 傳聞我的和親對象是個殘疾皇子耻警,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355