iOS 旋轉動畫添加3D效果

本文 出處 參考   http://blog.sina.com.cn/s/blog_71715bf801019ut9.html  本身mark下html

 例子代碼能夠在 http://download.csdn.net/detail/p709723778/5034622 下載
 本文重點在改變CALayer默認使用的正交投影,去使用透視投影矩陣。
iOS的UI是基於UIView類的,咱們能看到的每一個UI元素都是UIView或者UIView的子類。View按樹形結構組織起來,樹根是UIWindow。

View負責界面的交互和顯示,其中顯示部分由CALayer來完成。每一個UIView包含一個CALayer實例。能夠這麼認爲,UIView自己是不可見的,咱們能看到的都是CALayer,UIView只是負責對CALayer進行管理。

UIView的顯示設置都是對CALayer屬性的封裝,可是這層封裝掩蓋了CALayer提供的3D顯示功能。因此咱們想讓UIView顯示3D的效果的話,須要直接操做CALayer。

要操做CALayer對象,首先要在工程中包含QuartzCore.framework,在文件中import 頭文件。QuartzCore.framework中包含了CALayer以及CALayer一些官方子類的定義。

經過設置CALayer的transform屬性,可使CALayer產生3D空間內的平移、縮放、旋轉等變化。

第一個例子:繞座標軸的旋轉

原始場景如圖函數

 

IOS開發----3D <wbr>UI---CALayer的transform擴展

使用 image.layer.transform = CATransform3DMakeRotation(M_PI/6, 0, 0, 1); 繞Z軸旋轉30度後的效果

IOS開發----3D <wbr>UI---CALayer的transform擴展
使用 image.layer.transform = CATransform3DMakeRotation(M_PI/6, 0, 1, 0); 繞Y軸旋轉30度後的效果

IOS開發----3D <wbr>UI---CALayer的transform擴展
使用 image.layer.transform = CATransform3DMakeRotation(M_PI/6, 1, 0, 0); 繞X軸旋轉30度後的效果

IOS開發----3D <wbr>UI---CALayer的transform擴展
可以發現,繞Z軸的旋轉比較符合預期,可是繞X軸Y軸的旋轉只是在Y軸X軸上進行了一些縮放而已。這是由於,在CALayer的顯示系統中,默認的相機使用正交投影,正交投影沒有遠小近大效果,因此在本例中,只能形成相應軸上的縮放。

第二個例子:透視投影

CALayer默認使用正交投影,所以沒有遠小近大效果,並且沒有明確的API可使用透視投影矩陣。所幸能夠經過矩陣連乘本身構造透視投影矩陣。構造透視投影矩陣的代碼以下:
    CATransform3D CATransform3DMakePerspective(CGPoint center, float disZ)
    {
        CATransform3D transToCenter = CATransform3DMakeTranslation(-center.x, -center.y, 0);
        CATransform3D transBack = CATransform3DMakeTranslation(center.x, center.y, 0);
        CATransform3D scale = CATransform3DIdentity;
        scale.m34 = -1.0f/disZ;
        return CATransform3DConcat(CATransform3DConcat(transToCenter, scale), transBack);
    }

    CATransform3D CATransform3DPerspect(CATransform3D t, CGPoint center, float disZ)
    {
        return CATransform3DConcat(t, CATransform3DMakePerspective(center, disZ));
    }

這個函數的實現原理要參考計算機圖形學的3D變換部分,之後再作解釋。如今只須要了解接口的含義,center指的是相機 的位置,相機的位置是相對於要進行變換的CALayer的來講的,原點是CALayer的anchorPoint在整個CALayer的位置,例如CALayer的大小是(100, 200), anchorPoint值爲(0.5, 0.5),此時anchorPoint在整個CALayer中的位置就是(50, 100),正中心的位置。傳入透視變換的相機位置爲(0, 0),那麼相機所在的位置相對於CALayer就是(50, 100)。若是但願相機在左上角,則須要傳入(-50, -100)。disZ表示的是相機離z=0平面(也能夠理解爲屏幕)的距離。帶透視效果的旋轉,效果以下:

IOS開發----3D <wbr>UI---CALayer的transform擴展
CATransform3D rotate = CATransform3DMakeRotation(M_PI/6, 1, 0, 0);
    image.layer.transform = CATransform3DPerspect(rotate, CGPointMake(0, 0), 200);
IOS開發----3D <wbr>UI---CALayer的transform擴展
 CATransform3D rotate = CATransform3DMakeRotation(M_PI/6, 0, 0, 1);
    image.layer.transform = CATransform3DPerspect(rotate, CGPointMake(0, 0), 200);

IOS開發----3D <wbr>UI---CALayer的transform擴展
image的默認anchorPoint爲(0.5,0.5),也就是在圖片中心;眼睛在圖片中心點,距屏幕200單位。能夠觀察到,由於翻轉,使圖片的不一樣部分離屏幕距離不一樣,近大遠小的效果使立體感大大提高。饒Z軸的旋轉不由於透視產生變化,由於全部的點離屏幕距離相同,因此不會產生近大遠小的透視感。

第三個例子:更多的效果:

CALayer的旋轉和縮放是繞anchorPoint點的,改變anchorPoint的值,可使Layer繞不一樣的點而不僅是中心點旋轉縮放。在構造透視投影矩陣的例子中就能夠看到,CATransform3D可使用CATransform3DConcat函數鏈接起來以構造更復雜的變換。經過這些方法,能夠組合出更多的效果來。下面是個翻轉的動畫。使用UITimer

IOS開發----3D <wbr>UI---CALayer的transform擴展
- (void)update
    {
        static float angle = 0;
        angle += 0.05f;

CATransform3D transloate = CATransform3DMakeTranslation(0, 0, -200);
        CATransform3D rotate = CATransform3DMakeRotation(angle, 0, 1, 0);
        CATransform3D mat = CATransform3DConcat(rotate, transloate);
        image.layer.transform = CATransform3DPerspect(mat, CGPointMake(0, 0), 500);
    }

最後是兩個更復雜的例子。第一個是使用四張一樣大小的圖片圍成一個框,讓這個框動畫旋轉。

IOS開發----3D <wbr>UI---CALayer的transform擴展
CATransform3D move = CATransform3DMakeTranslation(0, 0, 160);
CATransform3D back = CATransform3DMakeTranslation(0, 0, -160);

    CATransform3D rotate0 = CATransform3DMakeRotation(-angle, 0, 1, 0);
    CATransform3D rotate1 = CATransform3DMakeRotation(M_PI_2-angle, 0, 1, 0);
    CATransform3D rotate2 = CATransform3DMakeRotation(M_PI_2*2-angle, 0, 1, 0);
    CATransform3D rotate3 = CATransform3DMakeRotation(M_PI_2*3-angle, 0, 1, 0);

CATransform3D mat0 = CATransform3DConcat(CATransform3DConcat(move, rotate0), back);
CATransform3D mat1 = CATransform3DConcat(CATransform3DConcat(move, rotate1), back);
CATransform3D mat2 = CATransform3DConcat(CATransform3DConcat(move, rotate2), back);
CATransform3D mat3 = CATransform3DConcat(CATransform3DConcat(move, rotate3), back);

image0.layer.transform = CATransform3DPerspect(mat0, CGPointZero, 500);
image1.layer.transform = CATransform3DPerspect(mat1, CGPointZero, 500);
image2.layer.transform = CATransform3DPerspect(mat2, CGPointZero, 500);
image3.layer.transform = CATransform3DPerspect(mat3, CGPointZero, 500);

上面的例子都使用UIImage的CALayer,但CALayer產生的動畫能夠應用在全部的UIView及子類上,下面是個普通界面的立體翻轉效果。

IOS開發----3D <wbr>UI---CALayer的transform擴展
float dis = 160 * 1.732f; CATransform3D move = CATransform3DMakeTranslation(0, 0, dis); CATransform3D back = CATransform3DMakeTranslation(0, 0, -dis);     CATransform3D rotate0 = CATransform3DMakeRotation(-angle, 0, 1, 0);     CATransform3D rotate1 = CATransform3DMakeRotation(-angle + M_PI/3.0f, 0, 1, 0); CATransform3D mat0 = CATransform3DConcat(CATransform3DConcat(move, rotate0), back); CATransform3D mat1 = CATransform3DConcat(CATransform3DConcat(move, rotate1), back); view0.layer.transform = CATransform3DPerspect(mat0, CGPointZero, 500); view1.layer.transform = CATransform3DPerspect(mat1, CGPointZero, 500);
相關文章
相關標籤/搜索