CGAffineTransform是iOS封裝的一套用于實(shí)現(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變換運(yùn)用得是矩陣乘法,通過最基礎(chǔ)的仿射方法init(a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat, tx: CGFloat, ty: CGFloat),可以發(fā)現(xiàn)他有6個(gè)參數(shù),可以拼出一下矩陣:

仿射變換的矩陣計(jì)算:

根據(jù)矩陣計(jì)算規(guī)則我們可以得到:
x' = ax + cy + tx
y' = bx + dy + ty
實(shí)踐運(yùn)用
平移

代碼如下:
/** 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}}

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

代碼如下:
/** 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為正值時(shí),會(huì)在x軸方向上縮放x倍,反之,則在縮放的基礎(chǔ)上沿著豎直線翻轉(zhuǎn);當(dāng)sy為正值時(shí),會(huì)在y軸方向上縮放y倍,反之,則在縮放的基礎(chǔ)上沿著水平線翻轉(zhuǎn)
效果圖:

旋轉(zhuǎn)

代碼如下:
/** 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)!))
}
效果圖:

注1: 當(dāng)angle為正值時(shí),逆時(shí)針旋轉(zhuǎn)坐標(biāo)系統(tǒng),反之順時(shí)針旋轉(zhuǎn)坐標(biāo)系統(tǒng)
CATransform3D仿射變換
3D仿射在iOS中是通過CATransform3D實(shí)現(xiàn)的,它有著與CGAffineTrans類似的一組API,但他們有個(gè)重要的區(qū)別在于CATransform3D的效果只能加在layer的transform屬性上,而CGAffineTransform直接加在View上。
3D仿射矩
類似于2D仿射,3D仿射也有一個(gè)基礎(chǔ)矩陣,并且比2D的多一個(gè)維度,計(jì)算規(guī)則如下:

根據(jù)矩陣計(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個(gè)存儲(chǔ)屬性,含義如下:
平移因子: 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)動(dòng)畫 */
CATransform3DMakeRotation(_ angle: CGFloat, _ x: CGFloat, _ y: CGFloat, _ z: CGFloat) -> CATransform3D
/** 縮放動(dòng)畫 */
CATransform3DMakeScale(_ sx: CGFloat, _ sy: CGFloat, _ sz: CGFloat) -> CATransform3D /** 位移動(dòng)畫 */
CATransform3DMakeTranslation(_ tx: CGFloat, _ ty: CGFloat, _ tz: CGFloat) -> CATransform3D
/** 檢查2個(gè)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
/* 這個(gè)是一個(gè)初始化矩陣,帶入矩陣算法計(jì)算后的結(jié)構(gòu)會(huì)得到 x'=x , y'=y , z'=z 它的作用是清除之前對(duì)矩陣設(shè)置的仿射效果,或者用來初始化一個(gè)原始無效果的仿射矩陣
[ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]*/
CATransform3DIdentity: CATransform3D
實(shí)戰(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
}
效果圖:

參考資料:http://liuyanwei.jumppo.com/2015/11/24/iOS-affine-transfermation-animation.html
--------------------- 本文來自 蝸牛非牛 的CSDN 博客 ,全文地址請(qǐng)點(diǎn)擊:https://blog.csdn.net/qq_34003239/article/details/82852822?utm_source=copy