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

转自:http://www.cnblogs.com/YouXianMing/p/3777778.html yaoxianming博客

时间: 2024-11-07 11:52:45

CATransformLayer的相关文章

iOS 动画Animation-4-5: CALayer子类:CATransformLayer

首先说明:这是一系列文章,参考本专题下其他的文章有助于你对本文的理解. 今天周六,希望大家都有一个愉快的周末. 今天来讲解一下CATransformLayer:CATransformLayer是一个专门用来创建三维视图的一个layer,也可以说是多个layer的集合.他没有多余的API,可以这么说,他只是承载了子layer. 下面就看一个例子,通过例子来讲解. 国际惯例先上图: 图就是这样的纯手工打造. 先创建一个CATransformLayer对象: var transformLayer =

使用CATransformLayer制作3D图像和动画

之前我们讲过可以用CALayer搭配CATransform3D来实现将View做3D旋转, 今天我们再看一个3D的新东西 CATransformLayer, 看名字就知道这个layer跟旋转有关, 那么具体是什么呢? 我们看他的头文件, 没有任何属性. 他其实是作为一个容器, 我们可以往里面添加其他的CALayer 比如我们要创建一个3D效果的立方体, 可以先创建一个CATransformlayer容器, 正方体的6个面我们以3D旋转后的Layer表示, 加入到容器中, 调整好每个面的角度和位置

CA*Layer(CATransformLayer--CAGradientLayer)

CATransformLayer CATransformLayer不同于普通的CALayer,因为它不能显示它自己的内容.只有当存在了一个能作用域子图层的变换它才真正存在.CATransformLayer并不平面化它的子图层,所以它能够用于构造一个层级的3D结构,比如我的手臂示例. 我们将通过旋转camara来解决图层平面化问题而不是像立方体示例代码中用的sublayerTransform.这是一个非常不错的技巧,但是只能作用域单个对象上,如果你的场景包含两个立方体,那我们就不能用这个技巧单独旋

[iOS Animation]-CALayer 专用图层 CATransformLayer

CATransformLayer 当我们在构造复杂的3D事物的时候,如果能够组织独立元素就太方便了.比如说,你想创造一个孩子的手臂:你就需要确定哪一部分是孩子的手腕,哪一部分是孩子的前臂,哪一部分是孩子的肘,哪一部分是孩子的上臂,哪一部分是孩子的肩膀等等. 当然是允许独立地移动每个区域的啦.以肘为指点会移动前臂和手,而不是肩膀.Core Animation图层很容易就可以让你在2D环境下做出这样的层级体系下的变换,但是3D情况下就不太可能,因为所有的图层都把他的孩子都平面化到一个场景中(第五章『

IOS Core Animation Advanced Techniques的学习笔记(五)

第六章:Specialized Layers   类别 用途 CAEmitterLayer 用于实现基于Core Animation粒子发射系统.发射器层对象控制粒子的生成和起源 CAGradientLayer 用于绘制一个颜色渐变填充图层的形状(所有圆角矩形边界内的部分) CAEAGLLayer/CAOpenGLLayer 用于设置需要使用OpenGL ES(iOS)或OpenGL(OS X)绘制的内容与内容储备. CAReplicatorLayer 当你想自动生成一个或多个子层的拷贝.复制器

自己总结的 iOS ,Mac 开源项目以及库,知识点------持续更新

自己在 git  上看到一个非常好的总结的东西,但是呢, fork  了几次,就是 fork  不到我的 git 上,干脆复制进去,但是,也是认真去每一个每一个去认真看了,并且也是补充了一些,感觉非常棒,所以好东西要分享,为啥用 CN 博客,有个好处,可以随时修改,可以持续更新,不用每次都要再发表,感觉这样棒棒的 我们 自己总结的iOS.mac开源项目及库,持续更新.... github排名 https://github.com/trending,github搜索:https://github.

IOS Core Animation Advanced Techniques的学习笔记(二)

[objc] view plaincopyprint?转载学习 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx { CGFloat width = 10.0f; //draw a thick red circle CGContextSetLineWidth(ctx, width); CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor); CG

iOS开发 非常全的三方库、插件、大牛博客等等

UI 下拉刷新 EGOTableViewPullRefresh- 最早的下拉刷新控件. SVPullToRefresh- 下拉刷新控件. MJRefresh- 仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉刷新功能.可以自定义上下拉刷新的文字说明.具体使用看"使用方法". (国人写) XHRefreshControl- XHRefreshControl 是一款高扩展性.低耦合度的下拉刷新.上提加载更多的组件.(国人写) CBStoreHo

iOS、mac开源项目及库汇总

UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉刷新功能.可以自定义上下拉刷新的文字说明.具体使用看“使用方法”. (国人写) XHRefreshControl – XHRefreshControl 是一款高扩展性.低耦合度的下拉刷新.上提加载更多的组件.(国人写) CBStoreHou