详解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];
}

 

 

时间: 2024-12-27 07:41:38

详解CATransformLayer的相关文章

详解Python中的type()方法的使用

  这篇文章主要介绍了详解Python中的type()方法的使用,是Python入门中的基础知识,需要的朋友可以参考下 type()方法返回传递变量的类型.如果传递变量是字典那么它将返回一个字典类型. 语法 以下是type()方法的语法: ? 1 type(dict) 参数 dict -- 这是字典 返回值 此方法返回传递变量的类型. 例子 下面的例子显示type()方法的使用 ? 1 2 3 4 #!/usr/bin/python   dict = {'Name': 'Zara', 'Age'

【转】java枚举使用详解

在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的"数据集",春夏秋冬四个数据元素组成了四季的"数据集". 在Java中如何更好的使用这些"数据集"呢?因此枚举便派上了用场,以下代码详细介绍了枚举的用法. Java代码   package com.ljq.test;      /**   * 枚举用法详解   *

状态模式(state pattern) 详解

状态模式(state pattern): 允许对象在内部状态改变时改变它的行为, 对象看起来好像修改了它的类. 建立Context类, 包含多个具体状态(concrete state)类的组合, 根据状态的不同调用具体的方法, state.handle(), 包含set\get方法改变状态. 状态接口(state interface), 包含抽象方法handle(), 具体状态类(concrete state)继承(implement)状态类(state), 实现handle()方法; 具体方法

kafka详解一、Kafka简介

背景:      当今社会各种应用系统诸如商业.社交.搜索.浏览等像信息工厂一样不断的生产出各种信息,在大数据时代,我们面临如下几个挑战: 如何收集这些巨大的信息 如何分析它        如何及时做到如上两点      以上几个挑战形成了一个业务需求模型,即生产者生产(produce)各种信息,消费者消费(consume)(处理分析)这些信息,而在生产者与消费者之间,需要一个沟通两者的桥梁-消息系统.      从一个微观层面来说,这种需求也可理解为不同的系统之间如何传递消息. Kafka诞生

Cocos2d-x win7 + vs2010 配置图文详解

Cocos2d-x win7 + vs2010 配置图文详解(亲测)   下载最新版的cocos2d-x.打开浏览器,输入cocos2d-x.org,然后选择Download,本教程写作时最新版本为cocos2d-1.01-x-0.9.1,具体下载位置如下图: 下载完之后,解压到当前文件夹.我把下载的程序放在F盘根目录,解压完毕之后,双击打开文件夹,看看里面有什么东西,红圈部分就是我们要安装使用的文件: 接下来,我们正式安装cocos2d-x到win7中去. 首先,双击上图中的cocos2d-w

ip-《TCP/IP 详解卷一》中90页中讲到,“由于子网号不相同,代理ARP不能使用”,这怎么理解?

问题描述 <TCP/IP 详解卷一>中90页中讲到,"由于子网号不相同,代理ARP不能使用",这怎么理解? <TCP/IP 详解卷一>中90页中讲到,"由于子网号不相同,代理ARP不能使用",这怎么理解? 解决方案 ARP主要用在一个子网中,用MAC地址来通信.数据链路层 不同子网,需要通过三层路由 解决方案二: 比如 N1 <-> GW <-> N2,N1和N2是同一个子网,GW上开启arp代理的效果是,N1和N2上

JS表格组件神器bootstrap table详解(基础版)_javascript技巧

一.Bootstrap Table的引入 关于Bootstrap Table的引入,一般来说还是两种方法: 1.直接下载源码,添加到项目里面来. 由于Bootstrap Table是Bootstrap的一个组件,所以它是依赖Bootstrap的,我们首先需要添加Bootstrap的引用. 2.使用我们神奇的Nuget 打开Nuget,搜索这两个包 Bootstrap已经是最新的3.3.5了,我们直接安装即可. 而Bootstrap Table的版本竟然是0.4,这也太坑爹了.所以博主建议Boot

网页文字该多大?文字字号详解

网页|详解 文字在网页上的应用: (只看小标题您就能知道这一部分要说什么了,为了避免罗嗦,在此文发布前决定把此处300余字删除,只保留了下面这一句.) 对于一个设计的好的网站来说,用户浏览时间最长的是文章正文. 中文网页文字的现状: 中文网页普遍使用12px和14px的宋体(simsun),这两种文字都可以加粗(font-weight: bold).这个规范似乎也成了网页设计师的基本 常识. 中国的网页设计师有这4种可供选择的文字表现方式,仅仅是4种,只有这4种,4种很小的文字.其中12px的宋

php-fpm配置详解

 这篇文章主要介绍了php-fpm配置详解,需要的朋友可以参考下 php5.3自带php-fpm   代码如下: /usr/local/php/etc/php-fpm.conf     pid = run/php-fpm.pid pid设置,默认在安装目录中的var/run/php-fpm.pid,建议开启   error_log = log/php-fpm.log 错误日志,默认在安装目录中的var/log/php-fpm.log   log_level = notice 错误级别. 可用级别