詳解CATransformLayer

CATransformLayer與CALayer有着細微的差異,但這些差異會影響到3D變換的動畫效果.ide

動畫都有座標系,以下所示(注意,這個不是iOS中的座標系,請勿對號入座):動畫

iOS中layer的錨點就在座標系的正中間.atom

layer的position能夠理解爲View的center.spa

 

實現帶有3d景深效果動畫:3d

複製代碼

////  RootViewController.m//  CATransformLayer////  Copyright (c) 2014年 Y.X. All rights reserved.//#import "RootViewController.h"#import "YXGCD.h"@interface RootViewController ()
@property (nonatomic, strong) GCDTimer  *timer;@end@implementation RootViewController#define V_CENTER_X           self.view.center.x#define V_CENTER_Y           self.view.center.y#define CG_COLOR(R, G, B, A) [UIColor colorWithRed:(R) green:(G) blue:(B) alpha:(A)].CGColor#define DEGREE(d)            ((d) * M_PI / 180.0f)

- (void)viewDidLoad
{
    [super viewDidLoad];    
    // 普通的一個layer
    CALayer *plane        = [CALayer layer];
    plane.anchorPoint = CGPointMake(0.5, 0.5);                         // 錨點
    plane.frame       = (CGRect){CGPointZero, CGSizeMake(100, 100)};   // 尺寸
    plane.position    = CGPointMake(V_CENTER_X, V_CENTER_Y);           // 位置
    plane.opacity         = 0.6;                                       // 背景透明度
    plane.backgroundColor = CG_COLOR(1, 0, 0, 1);                      // 背景色
    plane.borderWidth     = 3;                                         // 邊框寬度
    plane.borderColor     = CG_COLOR(1, 1, 1, 0.5);                    // 邊框顏色(設置了透明度)
    plane.cornerRadius    = 10;                                        // 圓角值    
    // 建立容器layer
    CALayer *container = [CALayer layer];
    container.frame    = self.view.bounds;
    [self.view.layer addSublayer:container];
    [container addSublayer:plane];    
    
    // 啓動定時器
    _timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
    [_timer event:^{        static float degree = 0.f;        
        // 起始值
        CATransform3D fromValue = CATransform3DIdentity;
        fromValue.m34           = 1.0/ -500;
        fromValue               = CATransform3DRotate(fromValue, degree, 0, 1, 0);        
        // 結束值
        CATransform3D toValue   = CATransform3DIdentity;
        toValue.m34             = 1.0/ -500;
        toValue                 = CATransform3DRotate(toValue, degree += 45.f, 0, 1, 0);        
        // 添加3d動畫
        CABasicAnimation *transform3D = [CABasicAnimation animationWithKeyPath:@"transform"];
        transform3D.duration  = 1.f;
        transform3D.fromValue = [NSValue valueWithCATransform3D:fromValue];
        transform3D.toValue   = [NSValue valueWithCATransform3D:toValue];
        plane.transform = toValue;
        [plane addAnimation:transform3D forKey:@"transform3D"];
        
    } timeInterval:NSEC_PER_SEC];
    [_timer start];
}@end

複製代碼

下圖中的m34值表明着景深效果,很是關鍵,其值越接近0,景深效果就愈加強烈code

若是寫成這樣子:orm

那麼顯示就會變成:blog

毫無3d感可言.ci

 

將景深效果添加到容器上面去咱們就能獲得以下的效果:animation

複製代碼

- (void)viewDidLoad
{
    [super viewDidLoad];    
    // 普通的一個layer
    CALayer *plane1        = [CALayer layer];
    plane1.anchorPoint = CGPointMake(0.5, 0.5);                         // 錨點
    plane1.frame       = (CGRect){CGPointZero, CGSizeMake(100, 100)};   // 尺寸
    plane1.position    = CGPointMake(60, V_CENTER_Y);                   // 位置
    plane1.opacity         = 0.6;                                       // 背景透明度
    plane1.backgroundColor = CG_COLOR(1, 0, 0, 1);                      // 背景色
    plane1.borderWidth     = 3;                                         // 邊框寬度
    plane1.borderColor     = CG_COLOR(1, 1, 1, 0.5);                    // 邊框顏色(設置了透明度)
    plane1.cornerRadius    = 10;                                        // 圓角值    
    // 普通的一個layer
    CALayer *plane2        = [CALayer layer];
    plane2.anchorPoint = CGPointMake(0.5, 0.5);                         // 錨點
    plane2.frame       = (CGRect){CGPointZero, CGSizeMake(100, 100)};   // 尺寸
    plane2.position    = CGPointMake(60 + 110, V_CENTER_Y);             // 位置
    plane2.opacity         = 0.6;                                       // 背景透明度
    plane2.backgroundColor = CG_COLOR(0, 1, 0, 1);                      // 背景色
    plane2.borderWidth     = 3;                                         // 邊框寬度
    plane2.borderColor     = CG_COLOR(1, 1, 1, 0.5);                    // 邊框顏色(設置了透明度)
    plane2.cornerRadius    = 10;                                        // 圓角值    
    // 建立容器layer
    CALayer *container = [CALayer layer];
    container.frame    = self.view.bounds;
    [self.view.layer addSublayer:container];
    
    CATransform3D plane_3D = CATransform3DIdentity;
    plane_3D.m34           = 1.0/ -500;
    plane_3D               = CATransform3DRotate(plane_3D, DEGREE(30), 0, 1, 0);
    container.transform    = plane_3D;
    
    [container addSublayer:plane1];
    [container addSublayer:plane2];
}

複製代碼

注意,下圖紅框中的值是很是關鍵的哦:

到這裏還沒講CATransformLayer呢,先看個例子:

效果以下:

複製代碼

- (void)viewDidLoad
{
    [super viewDidLoad];    
    // 普通的一個layer
    CALayer *plane1        = [CALayer layer];
    plane1.anchorPoint = CGPointMake(0.5, 0.5);                         // 錨點
    plane1.frame       = (CGRect){CGPointZero, CGSizeMake(100, 100)};   // 尺寸
    plane1.position    = CGPointMake(200, V_CENTER_Y);                  // 位置
    plane1.opacity         = 0.6;                                       // 背景透明度
    plane1.backgroundColor = CG_COLOR(1, 0, 0, 1);                      // 背景色
    plane1.borderWidth     = 3;                                         // 邊框寬度
    plane1.borderColor     = CG_COLOR(1, 1, 1, 0.5);                    // 邊框顏色(設置了透明度)
    plane1.cornerRadius    = 10;                                        // 圓角值    
    // Z軸平移
    CATransform3D plane1_3D = CATransform3DIdentity;
    plane1_3D               = CATransform3DTranslate(plane1_3D, 0, 0, -10);
    plane1.transform        = plane1_3D;    
    // 普通的一個layer
    CALayer *plane2        = [CALayer layer];
    plane2.anchorPoint = CGPointMake(0.5, 0.5);                         // 錨點
    plane2.frame       = (CGRect){CGPointZero, CGSizeMake(100, 100)};   // 尺寸
    plane2.position    = CGPointMake(200, V_CENTER_Y);                  // 位置
    plane2.opacity         = 0.6;                                       // 背景透明度
    plane2.backgroundColor = CG_COLOR(0, 1, 0, 1);                      // 背景色
    plane2.borderWidth     = 3;                                         // 邊框寬度
    plane2.borderColor     = CG_COLOR(1, 1, 1, 0.5);                    // 邊框顏色(設置了透明度)
    plane2.cornerRadius    = 10;                                        // 圓角值    
    // Z軸平移
    CATransform3D plane2_3D = CATransform3DIdentity;
    plane2_3D               = CATransform3DTranslate(plane2_3D, 0, 0, -30);
    plane2.transform        = plane2_3D;    
    // 建立容器layer
    CALayer *container = [CALayer layer];
    container.frame    = self.view.bounds;
    [self.view.layer addSublayer:container];    
    // 以Y軸爲座標系,旋轉45度
    CATransform3D t = CATransform3DIdentity;
    t.m34 = 1.0/-500;
    t = CATransform3DRotate(t, DEGREE(45), 0, 1, 0);
    container.transform = t;
    
    [container addSublayer:plane1];
    [container addSublayer:plane2];
}

複製代碼

若是把上圖的CALayer替換成下圖的CATransformLayer

則會產生以下的效果:

看到上面的圖,你應該就明白了CATransformLayer當作容器是爲了給裏面的Layer提供景深效果用的.

再來作成動畫看看效果吧:

複製代碼

- (void)viewDidLoad
{
    [super viewDidLoad];    
    // 普通的一個layer
    CALayer *plane1        = [CALayer layer];
    plane1.anchorPoint = CGPointMake(0.5, 0.5);                         // 錨點
    plane1.frame       = (CGRect){CGPointZero, CGSizeMake(100, 100)};   // 尺寸
    plane1.position    = CGPointMake(200, V_CENTER_Y);                  // 位置
    plane1.opacity         = 0.6;                                       // 背景透明度
    plane1.backgroundColor = CG_COLOR(1, 0, 0, 1);                      // 背景色
    plane1.borderWidth     = 3;                                         // 邊框寬度
    plane1.borderColor     = CG_COLOR(1, 1, 1, 0.5);                    // 邊框顏色(設置了透明度)
    plane1.cornerRadius    = 10;                                        // 圓角值    
    // Z軸平移
    CATransform3D plane1_3D = CATransform3DIdentity;
    plane1_3D               = CATransform3DTranslate(plane1_3D, 0, 0, -10);
    plane1.transform        = plane1_3D;    
    // 普通的一個layer
    CALayer *plane2        = [CALayer layer];
    plane2.anchorPoint = CGPointMake(0.5, 0.5);                         // 錨點
    plane2.frame       = (CGRect){CGPointZero, CGSizeMake(100, 100)};   // 尺寸
    plane2.position    = CGPointMake(200, V_CENTER_Y);                  // 位置
    plane2.opacity         = 0.6;                                       // 背景透明度
    plane2.backgroundColor = CG_COLOR(0, 1, 0, 1);                      // 背景色
    plane2.borderWidth     = 3;                                         // 邊框寬度
    plane2.borderColor     = CG_COLOR(1, 1, 1, 0.5);                    // 邊框顏色(設置了透明度)
    plane2.cornerRadius    = 10;                                        // 圓角值    
    // Z軸平移
    CATransform3D plane2_3D = CATransform3DIdentity;
    plane2_3D               = CATransform3DTranslate(plane2_3D, 0, 0, -30);
    plane2.transform        = plane2_3D;    
    // 建立容器layer
    CATransformLayer *container = [CATransformLayer layer];
    container.frame    = self.view.bounds;
    [self.view.layer addSublayer:container];
    [container addSublayer:plane1];
    [container addSublayer:plane2];    
    // 啓動定時器
    _timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
    [_timer event:^{        static float degree = 0.f;        
        // 起始值
        CATransform3D fromValue = CATransform3DIdentity;
        fromValue.m34           = 1.0/ -500;
        fromValue               = CATransform3DRotate(fromValue, degree, 0, 1, 0);        
        // 結束值
        CATransform3D toValue   = CATransform3DIdentity;
        toValue.m34             = 1.0/ -500;
        toValue                 = CATransform3DRotate(toValue, degree += 45.f, 0, 1, 0);        
        // 添加3d動畫
        CABasicAnimation *transform3D = [CABasicAnimation animationWithKeyPath:@"transform"];
        transform3D.duration  = 1.f;
        transform3D.fromValue = [NSValue valueWithCATransform3D:fromValue];
        transform3D.toValue   = [NSValue valueWithCATransform3D:toValue];
        container.transform = toValue;
        [container addAnimation:transform3D forKey:@"transform3D"];
        
    } timeInterval:NSEC_PER_SEC];
    [_timer start];
}

複製代碼

相關文章
相關標籤/搜索