仿射變換-CGAffineTransform

CGAffineTransform是iOS封裝的一套用于實現(xiàn)仿射變換效果的API棠赛,用于繪制2D圖形员帮,可以進(jìn)行位移次坡、旋轉(zhuǎn)溺拱、縮放、疊加等效果蝙泼,常用方法如下:

/** 位移仿射 */
init(translationX tx: CGFloat, y ty: CGFloat)
translatedBy(x tx: CGFloat, y ty: CGFloat)

/** 縮放仿射 */
init(scaleX sx: CGFloat, y sy: CGFloat)
scaledBy(x sx: CGFloat, y sy: CGFloat) 

/** 旋轉(zhuǎn)仿射 */init(rotationAngle angle: CGFloat)
rotated(by angle: CGFloat) -> CGAffineTransform

/** 疊加仿射 */
concatenating(_ t2: CGAffineTransform)

CGAffineTransform原理

CGAffineTransform --view的2D變換運用得是矩陣乘法程剥,通過最基礎(chǔ)的仿射方法init(a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat, tx: CGFloat, ty: CGFloat),可以發(fā)現(xiàn)他有6個參數(shù)汤踏,可以拼出一下矩陣:

矩陣.png

仿射變換的矩陣計算:

屏幕快照 2018-09-26 下午2.40.13.png

根據(jù)矩陣計算規(guī)則我們可以得到:

x' = ax + cy + tx
y' = bx + dy + ty

實踐運用

平移

屏幕快照 2018-09-26 下午3.29.21.png

代碼如下:

/** t' = [ 1 0 0 1 tx ty ] */
UIView.animate(withDuration: 1) {  
  _ = CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 100, ty: 100)   
  self.redView?.transform = CGAffineTransform(translationX: 100, y: 100)  
  print(NSStringFromCGRect((self.redView?.frame)!)) 
}

輸出結(jié)果為:{{200, 200}, {100, 100}}

QQ20180926-145732-HD.gif

注: 當(dāng)tx為正值時,會向x軸正方向平移,反之,則向x軸負(fù)方向平移;當(dāng)ty為正值時,會向y軸正方向平移,反之,則向y軸負(fù)方向平移

縮放

屏幕快照 2018-09-26 下午3.31.24.png

代碼如下:

/** t' = [ sx 0 0 sy 0 0 ] */
UIView.animate(withDuration: 1) {  
  self.redView?.transform = CGAffineTransform(scaleX: 2, y: 2)
  print(NSStringFromCGRect((self.redView?.frame)!))
}

注: 當(dāng)sx為正值時,會在x軸方向上縮放x倍,反之,則在縮放的基礎(chǔ)上沿著豎直線翻轉(zhuǎn);當(dāng)sy為正值時,會在y軸方向上縮放y倍,反之,則在縮放的基礎(chǔ)上沿著水平線翻轉(zhuǎn)

效果圖:

QQ20180926-153401-HD.gif

旋轉(zhuǎn)

屏幕快照 2018-09-26 下午3.35.31.png

代碼如下:

/** t' = [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] */
UIView.animate(withDuration: 1) {  
self.redView?.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI_2))  print(NSStringFromCGRect((self.redView?.frame)!))
}

效果圖:

QQ20180926-154049-HD.gif

注1: 當(dāng)angle為正值時,時針旋轉(zhuǎn)坐標(biāo)系統(tǒng),反之時針旋轉(zhuǎn)坐標(biāo)系統(tǒng)

CATransform3D仿射變換

3D仿射在iOS中是通過CATransform3D實現(xiàn)的织鲸,它有著與CGAffineTrans類似的一組API,但他們有個重要的區(qū)別在于CATransform3D的效果只能加在layer的transform屬性上溪胶,而CGAffineTransform直接加在View上搂擦。

3D仿射矩

類似于2D仿射,3D仿射也有一個基礎(chǔ)矩陣哗脖,并且比2D的多一個維度瀑踢,計算規(guī)則如下:

屏幕快照 2018-09-26 下午3.47.33.png

根據(jù)矩陣計算規(guī)則我們可以得到:

x' = m11x + m21y + m31*z + m41(tx)

y' = m12x + m22y + m32*z + m42(ty)

z' = m13x + m23y + m33*z + m43(tx)

CATransform3D有16個存儲屬性,含義如下:

平移因子: m41(x位置) m42(y位置) m43(z位置) 縮放因子: m11(x位置) m22(y位置)
切變因子: m21(x位置) m12(y位置)
旋轉(zhuǎn)因子: m13(x位置) m31(y位置)
透視因子: m34(有旋轉(zhuǎn)才能看出效果

常用方法:

/** 旋轉(zhuǎn)動畫 */
CATransform3DMakeRotation(_ angle: CGFloat, _ x: CGFloat, _ y: CGFloat, _ z: CGFloat) -> CATransform3D 
/** 縮放動畫 */
CATransform3DMakeScale(_ sx: CGFloat, _ sy: CGFloat, _ sz: CGFloat) -> CATransform3D /** 位移動畫 */
CATransform3DMakeTranslation(_ tx: CGFloat, _ ty: CGFloat, _ tz: CGFloat) -> CATransform3D 
/** 檢查2個3D仿射效果是否相同 */
CATransform3DEqualToTransform(_ a: CATransform3D, _ b: CATransform3D) -> Bool 
/** 檢查是否有做過仿射3D效果 */
CATransform3DIsIdentity(_ t: CATransform3D) -> Bool 
/** 3D仿射轉(zhuǎn)換成2D仿射 */
CATransform3DGetAffineTransform(_ t: CATransform3D) -> CGAffineTransform 
/** 2D仿射轉(zhuǎn)換成3D仿射 */
CATransform3DMakeAffineTransform(_ m: CGAffineTransform) -> CATransform3D 
/** 3D仿射效果反轉(zhuǎn)(反效果才避,比如原來擴(kuò)大橱夭,就變成縮小) */
CATransform3DInvert(_ t: CATransform3D) -> CATransform3D 
/** 疊加3D仿射效果 */
CATransform3DConcat(_ a: CATransform3D, _ b: CATransform3D) -> CATransform3D 
/*    這個是一個初始化矩陣工扎,帶入矩陣算法計算后的結(jié)構(gòu)會得到    x'=x , y'=y , z'=z    它的作用是清除之前對矩陣設(shè)置的仿射效果徘钥,或者用來初始化一個原始無效果的仿射矩陣    
        [ 1 0 0 0 ]    
        [ 0 1 0 0 ]    
        [ 0 0 1 0 ]    
        [ 0 0 0 1 ]*/
CATransform3DIdentity: CATransform3D

實戰(zhàn):

代碼如下:

   static var j = 0
    @objc func touches3DTransform() {
        switch ViewController.j {
        case 0:
            /** 旋轉(zhuǎn) */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DMakeRotation(CGFloat(M_PI), 0, 0, 1)
            }
        case 1:
            /** 平移 t' =  [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1] */
            /**  */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DMakeTranslation(100, 100, 100)
            }
        case 2:
            /** 縮放 t' = [sx 0 0 0; 0 sy 0 0; 0 0 sz 0; 0 0 0 1] */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform =  CATransform3DMakeScale(2, 1, 1)
            }
        case 3:
            /** 旋轉(zhuǎn)縮放 t' = rotation(angle, x, y, z) * t */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DRotate(CATransform3DMakeScale(1, 1, 1), CGFloat(M_PI), 0, 1, 0)
            }
            print(NSStringFromCGRect((blueBtn?.frame)!))
        case 4:
            /** 反轉(zhuǎn) */
            UIView.animate(withDuration: 1) {
                self.blueBtn?.layer.transform = CATransform3DInvert(CATransform3DMakeScale(2, 2, 1))
            }
            print(NSStringFromCGRect((blueBtn?.frame)!))
        default:
            print("other")
        }
        ViewController.j += 1
    }

效果圖:

縮放旋轉(zhuǎn).gif

參考資料:http://liuyanwei.jumppo.com/2015/11/24/iOS-affine-transfermation-animation.html

--------------------- 本文來自 蝸牛非牛 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/qq_34003239/article/details/82852822?utm_source=copy

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肢娘,一起剝皮案震驚了整個濱河市呈础,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌橱健,老刑警劉巖而钞,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拘荡,居然都是意外死亡臼节,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門珊皿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來网缝,“玉大人,你說我怎么就攤上這事蟋定》垭” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵驶兜,是天一觀的道長扼仲。 經(jīng)常有香客問我远寸,道長,這世上最難降的妖魔是什么屠凶? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任驰后,我火速辦了婚禮,結(jié)果婚禮上矗愧,老公的妹妹穿的比我還像新娘灶芝。我一直安慰自己,他們只是感情好唉韭,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布监署。 她就那樣靜靜地躺著,像睡著了一般纽哥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上栖秕,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天春塌,我揣著相機(jī)與錄音,去河邊找鬼簇捍。 笑死只壳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暑塑。 我是一名探鬼主播吼句,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼事格!你這毒婦竟也來了惕艳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驹愚,失蹤者是張志新(化名)和其女友劉穎远搪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逢捺,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡谁鳍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了劫瞳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倘潜。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖志于,靈堂內(nèi)的尸體忽然破棺而出涮因,到底是詐尸還是另有隱情,我是刑警寧澤恨憎,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布蕊退,位于F島的核電站郊楣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏瓤荔。R本人自食惡果不足惜净蚤,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望输硝。 院中可真熱鬧今瀑,春花似錦、人聲如沸点把。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郎逃。三九已至哥童,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間褒翰,已是汗流浹背贮懈。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留优训,地道東北人朵你。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像揣非,于是被迫代替她去往敵國和親抡医。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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