iOS CATransform3D

緊接之前寫的CGAffineTransform在此對3D空間內(nèi)的動畫旋轉(zhuǎn)進行分析下。當然在寫這篇文章的時候也在網(wǎng)上查閱了大量的資料,雖然都很有幫助,但是我總覺得缺點什么,于是再結(jié)合自己的想法,在這里記錄一下。在之前的文章中也說過,CATransform3D主要是針對CALayer3D旋轉(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矩陣乘法
IMG_0730.JPG
結(jié)果轉(zhuǎn)換
IMG_0731.JPG
對結(jié)果進行分析

先看x',由于只有m11是在直接改變x的倍數(shù),而m41是在改變x的坐標,所以我們可以很直觀的得到下面的結(jié)論:

m11:控制x方向上的縮放
m14:控制x方向上的平移

以此類推:我們也可以得到關(guān)于yz軸上的關(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)的幾個變量是怎么回事。
這里我先做了一個簡單的測試,來對比2D3D的區(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;
        }
        
    }];
}

效果圖

2d_3d.gif

從上面的效果圖我們可以看到兩者的效果一模一樣,那么為什么呢?
分析:
第一幅圖由于是在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)該只有xy發(fā)生了變化,關(guān)于三維空間的旋轉(zhuǎn),我也是想了很久,這里給大家一個連接,三維坐標系的旋轉(zhuǎn)矩陣,通過這里大家應(yīng)該就能非常明白了,如果繞z軸旋轉(zhuǎn),那么發(fā)生變化的xy的值可以用下面表示,根據(jù)三維旋轉(zhuǎn)中繞zθ度得到的結(jié)果

12.png

再結(jié)合上面的

IMG_0731.JPG

我們一對比,就能得出

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的方式進行。

平移


平移.png

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"];

縮放

縮放.png

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)

旋轉(zhuǎn).png
//沿著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.CATransform3DCGAffineTransform相互轉(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的了解,就差不多這些了,后面我會補充些動畫,看到炫酷的動畫,心里就癢癢啊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容