详解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];// 普通的一个layerCALayer *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;                                        // 圆角值// 创建容器layerCALayer *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];// 普通的一个layerCALayer *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;                                        // 圆角值// 普通的一个layerCALayer *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;                                        // 圆角值// 创建容器layerCALayer *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];// 普通的一个layerCALayer *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;// 普通的一个layerCALayer *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;// 创建容器layerCALayer *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];// 普通的一个layerCALayer *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;// 普通的一个layerCALayer *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;// 创建容器layerCATransformLayer *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];
}

详解CATransformLayer相关推荐

  1. 从命令行到IDE,版本管理工具Git详解(远程仓库创建+命令行讲解+IDEA集成使用)

    首先,Git已经并不只是GitHub,而是所有基于Git的平台,只要在你的电脑上面下载了Git,你就可以通过Git去管理"基于Git的平台"上的代码,常用的平台有GitHub.Gi ...

  2. JVM年轻代,老年代,永久代详解​​​​​​​

    秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...

  3. docker常用命令详解

    docker常用命令详解 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: Doc ...

  4. 通俗易懂word2vec详解词嵌入-深度学习

    https://blog.csdn.net/just_so_so_fnc/article/details/103304995 skip-gram 原理没看完 https://blog.csdn.net ...

  5. 深度学习优化函数详解(5)-- Nesterov accelerated gradient (NAG) 优化算法

    深度学习优化函数详解系列目录 深度学习优化函数详解(0)– 线性回归问题 深度学习优化函数详解(1)– Gradient Descent 梯度下降法 深度学习优化函数详解(2)– SGD 随机梯度下降 ...

  6. CUDA之nvidia-smi命令详解---gpu

    nvidia-smi是用来查看GPU使用情况的.我常用这个命令判断哪几块GPU空闲,但是最近的GPU使用状态让我很困惑,于是把nvidia-smi命令显示的GPU使用表中各个内容的具体含义解释一下. ...

  7. Bert代码详解(一)重点详细

    这是bert的pytorch版本(与tensorflow一样的,这个更简单些,这个看懂了,tf也能看懂),地址:https://github.com/huggingface/pytorch-pretr ...

  8. CRF(条件随机场)与Viterbi(维特比)算法原理详解

    摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...

  9. pytorch nn.LSTM()参数详解

    输入数据格式: input(seq_len, batch, input_size) h0(num_layers * num_directions, batch, hidden_size) c0(num ...

  10. Java集合详解之Map

    一.首先看看集合框架体系图 从图中可以看到,Map接口扩展了Iterator接口,关于Iterator接口详解请移步:Iterator接口详解 二.Map是什么? Map<k,v>使用键值 ...

最新文章

  1. js array push 添加内容
  2. Android自定义控件:动画类---逐帧动画AnimationDrawable
  3. VTK:Rendering之InterpolateCamera
  4. 开启简单的laravel5 MVC模式
  5. redis下并发问题解决方案
  6. windows--bat--删除当前脚本del %0
  7. ajax-登陆+验证码
  8. python如何设置双索引_python – 设置值多索引熊猫
  9. HDU-1863-畅通工程
  10. Julia: Dict类型 与 Symbol
  11. gimp中文版教程_Gimp中文经典入门实用教程(合辑).pdf
  12. Aria2Gee 教程
  13. Adb 微信APP降级工具使用教程
  14. [车]上海外地“苏牌”竟要万元
  15. 章文嵩坐镇淘宝双11流量作战室
  16. 获取sender名称
  17. 2021-10-28项目集管理PgMP:刷新项目管理思维与架构︱项目管理者联盟联合创始人宣晓锋
  18. Lua 求表中元素的最大值和最小值
  19. 微信小程序使用canvas绘图
  20. 解决“ImportError: cannot import name ‘_validate_lengths‘”问题

热门文章

  1. eclipse导入github项目(踩多个坑后发现这个最实用)
  2. python ljust函数,Python 字符串左对齐-Python 指定字符串左对齐-python ljust() 函数-python ljust() 函数用法-嗨客网...
  3. 网和aoe网的区别_【专定网】你知道到亚克力鱼缸与超白缸的区别吗?测评结果给你答案...
  4. java加按钮_用java写一个简单的学生信息管理系统
  5. 样本分成训练集和测试集_吴恩达深度学习笔记(64)-开发集和测试集的大小分配...
  6. SQL Server-【知识与实战I】条件查询、比较运算符查询、模糊查询、枚举查询、范围查询、空值查询、多重条件查询
  7. L1-030 一帮一 (15 分)—团体程序设计天梯赛
  8. 12.TCP的成块数据流
  9. 蓝桥杯十六进制转化为十进制
  10. Appium——元素定位