緊接之前寫的CGAffineTransform在此對3D空間內(nèi)的動畫旋轉(zhuǎn)進行分析下。當然在寫這篇文章的時候也在網(wǎng)上查閱了大量的資料,雖然都很有幫助,但是我總覺得缺點什么,于是再結(jié)合自己的想法,在這里記錄一下。在之前的文章中也說過,CATransform3D主要是針對CALayer的3D旋轉(zhuǎn),關(guān)于CALayer的詳細屬性就不在此處講解了,相信大家都有了解。首先我們先看下API:
struct CATransform3D
{
CGFloat m11, m12, m13, m14;
CGFloat m21, m22, m23, m24;
CGFloat m31, m32, m33, m34;
CGFloat m41, m42, m43, m44;
};
typedef struct CATransform3D CATransform3D;
這就是CATransform3D的結(jié)構(gòu),從API中我們可以看到這其實也是一個矩陣,只不過是一個 4*4的矩陣,我們還是和之前那樣分析的一樣來分析,先看看矩陣乘法
CATransform3D矩陣乘法
結(jié)果轉(zhuǎn)換
對結(jié)果進行分析
先看x',由于只有m11是在直接改變x的倍數(shù),而m41是在改變x的坐標,所以我們可以很直觀的得到下面的結(jié)論:
m11:控制x方向上的縮放
m14:控制x方向上的平移
以此類推:我們也可以得到關(guān)于y和z軸上的關(guān)系
m22:控制y方向上的縮放
m24:控制y方向上的平移
m33:控制z方向上的縮放
m34:控制z方向上的平移
那么剩余的變量我們怎么去理解呢?如果一個圖形不是平移或者縮放的話,那么肯定就是發(fā)生了旋轉(zhuǎn) ,所以剩余的應(yīng)該是控制做圖形的旋轉(zhuǎn)。即:
m12、m13、m21、m23、m31、m32控制旋轉(zhuǎn)
那么還有m14、m24、m34、m44了,這個在后面再講講,現(xiàn)在我們先來看看關(guān)于旋轉(zhuǎn)的幾個變量是怎么回事。
這里我先做了一個簡單的測試,來對比2D和3D的區(qū)別。
先看代碼
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(30, 80, 40, 40);
[button addTarget:self action:@selector(CATransform3DTouch:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"test" forState:UIControlStateNormal];
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[self.view addSubview:button];
UIImageView *image_one = [[UIImageView alloc] initWithFrame:CGRectMake(0, 120, 150, 100)];
image_one.image = [UIImage imageNamed:@"fire_class_1"];
[self.view addSubview:image_one];
UIImageView *image_two = [[UIImageView alloc] initWithFrame:CGRectMake(40, 200, 150, 100)];
image_two.image = [UIImage imageNamed:@"fire_class_2"];
[self.view addSubview:image_two];
self.imageone = image_one;
self.imagetwo = image_two;
}
- (void)CATransform3DTouch:(UIButton *)sender
{
sender.selected = !sender.selected;
[UIView animateWithDuration:2 animations:^{
if (sender.selected)
{
//CALayer的3D旋轉(zhuǎn)
CATransform3D turnTrans = CATransform3DMakeRotation(M_PI/4, 0, 0, 1);
self.imageone.layer.transform = turnTrans;
//UIview的2D旋轉(zhuǎn)
self.imagetwo.transform = CGAffineTransformMakeRotation(M_PI/4);
}
else
{
self.imageone.layer.transform = CATransform3DIdentity;
self.imagetwo.transform = CGAffineTransformIdentity;
}
}];
}
效果圖

從上面的效果圖我們可以看到兩者的效果一模一樣,那么為什么呢?
分析:
第一幅圖由于是在3D的坐標系內(nèi)進行旋轉(zhuǎn),而且從代碼中可以看到,我在z軸上的值不為0,我們先在心中建立一個空間坐標系,假如我們將一根針直接插入屏幕上(不要真的去拿一根針哈,7壞了,我可賠不起,哈哈),當作我們的z軸,那么我們現(xiàn)在繞z軸旋轉(zhuǎn),其實就和2D旋轉(zhuǎn)一樣,都是在平面上進行旋轉(zhuǎn)。根據(jù)旋轉(zhuǎn)的角度我們可以計算出旋轉(zhuǎn)后的變化,由于這里是繞z軸旋轉(zhuǎn)的,所以應(yīng)該只有x和y發(fā)生了變化,關(guān)于三維空間的旋轉(zhuǎn),我也是想了很久,這里給大家一個連接,三維坐標系的旋轉(zhuǎn)矩陣,通過這里大家應(yīng)該就能非常明白了,如果繞z軸旋轉(zhuǎn),那么發(fā)生變化的x和y的值可以用下面表示,根據(jù)三維旋轉(zhuǎn)中繞z旋θ度得到的結(jié)果

再結(jié)合上面的
我們一對比,就能得出
m21:和m23一起決定y軸的旋轉(zhuǎn)
同樣的道理:
m31:和m32一起決定z軸的旋轉(zhuǎn)
m12:和m13一起決定x軸的旋轉(zhuǎn)
到現(xiàn)在我們就剩下m14、m24、m34、m44了,關(guān)于這幾個,我在網(wǎng)上查閱了資料。
其中m14和m24都沒有什么說明,m34為透視效果,要操作的這個對象要有旋轉(zhuǎn)的角度,否則沒有效果。當然,z方向上得有變化才會有透視效果。m44:初始為1,具體是用來干什么的,暫時不知......
下面來看看CATransform3D中的函數(shù)的意思
1.非平移,旋轉(zhuǎn),縮放類
//沒有變化,最初的樣子
/* The identity transform: [1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]. */
const CATransform3D CATransform3DIdentity;
//判斷一個transform3D的對象是否是最初的樣子
/* Returns true if 't' is the identity transform. */
bool CATransform3DIsIdentity (CATransform3D t);
//比較兩個transform3D對象是否等同
/* Returns true if 'a' is exactly equal to 'b'. */
bool CATransform3DEqualToTransform (CATransform3D a, CATransform3D b);
//將兩個 transform3D對象變換屬性進行疊加,返回一個新的transform3D對象
/* Concatenate 'b' to 'a' and return the result: t' = a * b. */
CATransform3D CATransform3DConcat (CATransform3D a, CATransform3D b);
//類似CGAffineTransform 中的CGAffineTransformInvert 代表 反向變換
/* Invert 't' and return the result. Returns the original matrix if 't'
* has no inverse. */
CA_EXTERN CATransform3D CATransform3DInvert (CATransform3D t)
2.平移,縮放,旋轉(zhuǎn)類
//-----平移
//返回一個平移變換的transform3D對象 tx,ty,tz對應(yīng)x,y,z軸的平移
CATransform3D CATransform3DMakeTranslation (CGFloat tx, CGFloat ty, CGFloat tz);
//在某個transform3D變換的基礎(chǔ)上進行平移變換,t是上一個transform3D,其他參數(shù)同上
CATransform3D CATransform3DTranslate (CATransform3D t, CGFloat tx, CGFloat ty, CGFloat tz);
//-----縮放
//x,y,z分別對應(yīng)x軸,y軸,z軸的縮放比例
CATransform3D CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);
//在一個transform3D變換的基礎(chǔ)上進行縮放變換,其他參數(shù)同上
CATransform3D CATransform3DScale (CATransform3D t, CGFloat sx, CGFloat sy, CGFloat sz);
//-----旋轉(zhuǎn)
//angle參數(shù)是旋轉(zhuǎn)的角度 ,x,y,z決定了旋轉(zhuǎn)圍繞的中軸,取值為-1 — 1之間,如(1,0,0),則是繞x軸旋轉(zhuǎn),(0.5,0.5,0),則是繞x軸與y軸中間45度為軸旋轉(zhuǎn)
CATransform3D CATransform3DMakeRotation (CGFloat angle, CGFloat x, CGFloat y, CGFloat z);
//在一個transform3D的基礎(chǔ)上進行旋轉(zhuǎn)變換,其他參數(shù)如上
CATransform3D CATransform3DRotate (CATransform3D t, CGFloat angle, CGFloat x, CGFloat y, CGFloat z);
針對上面的平移,縮放,旋轉(zhuǎn),我們也可以用kvo的方式進行。
平移

kvo方法
//x軸方向平移
[self.imageone.layer setValue:@(100) forKeyPath:@"transform.translation.x"];
//y軸方向平移
[self.imageone.layer setValue:@(100) forKeyPath:@"transform.translation.y"];
//沿著z方向平移
[self.imageone.layer setValue:@(100) forKeyPath:@"transform.translation.z"];
縮放

kvo方法
//沿著x軸方向放大1.5倍數(shù)
[self.imageone.layer setValue:@(1.5)forKeyPath:@"transform.scale.x"];
//沿著y軸方向放大1.5倍數(shù)
[self.imageone.layer setValue:@(1.5)forKeyPath:@"transform.scale.y"];
//沿著z軸方向放大1.5倍數(shù)
[self.imageone.layer setValue:@(1.5)forKeyPath:@"transform.scale.z"];
旋轉(zhuǎn)

//沿著z軸旋轉(zhuǎn)
[self.imageone.layer setValue:@(M_PI_2) forKeyPath:@"transform.rotation.z"];
//沿著x軸旋轉(zhuǎn)
[self.imageone.layer setValue:@(M_PI_2) forKeyPath:@"transform.rotation.x"];
//沿著y軸旋轉(zhuǎn)
[self.imageone.layer setValue:@(M_PI_2) forKeyPath:@"transform.rotation.y"];
3.CATransform3D和CGAffineTransform相互轉(zhuǎn)換
//將一個CGAffineTransform轉(zhuǎn)化為CATransform3D
CATransform3D CATransform3DMakeAffineTransform (CGAffineTransform m);
//判斷一個CATransform3D是否可以轉(zhuǎn)換為CGAffineTransform
bool CATransform3DIsAffine (CATransform3D t);
//將CATransform3D轉(zhuǎn)換為CGAffineTransform
CGAffineTransform CATransform3DGetAffineTransform (CATransform3D t);
到此關(guān)于我對CATransform3D的了解,就差不多這些了,后面我會補充些動畫,看到炫酷的動畫,心里就癢癢啊。