https://github.com/YouXianMing

详解CATransformLayer

详解CATransformLayer

 

CATransformLayer与CALayer有着细微的差别,但这些差别会影响到3D变换的动画效果.

动画都有坐标系,如下所示(注意,这个不是iOS中的坐标系,请勿对号入座):

iOS中layer的锚点就在坐标系的正中间.

layer的position可以理解为View的center.

 

实现带有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,景深效果就越发强烈

如果写成这样子:

那么显示就会变成:

毫无3d感可言.

 

将景深效果添加到容器上面去我们就能得到如下的效果:

- (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];
}

 

 

 

posted @ 2014-06-09 14:46  YouXianMing  阅读(3193)  评论(0编辑  收藏  举报