热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iOSCoreAnimationAdvancedTechniques变换

读《iOSCoreAnimationAdvancedTechni

上四章节:

  1. 图层树
  2. 图层的寄宿图
  3. 图层几何学
  4. 图层视觉效果

这篇随笔主要介绍有关图层变换。

  • 变换:
    • 对图层旋转,摆放或者扭曲的CGAffineTransform,可以将扁平物体转换成三维空间对象的CATransform3D
  • 仿射(图层中平行的两条线在变换之后任然保持平行)变换:
    • CGAffineTransform属性(仅对2D变换有效)
      • 用于在二维空间做旋转,缩放与平移

CALayer的affineTransform属性就是一个CGAffineTransform类型对象,UIView对应的属性为transform属性
CALayer的transform属性是一个CATransform3D类型而不是CGAffineTransform类型
系统提供创建CGAffineTransform实例对象的主要3个方法:

    1. CGAffineTransformMakeRotation(CGFloat angle);//旋转
    2. CGAffineTransformMakeScale(CGFloat sx,CGFloat sy);//缩放
    3. CGAffineTransformMakeTranslation(CGFloat tx,CGFloat ty);//平移
      • 使用例子:
      • CGAffineTransform transform=CGAffineTransformMakeRotation(M_PI_4);//iOS的变换函数使用弧度而不是角度作为单位
      • myView.layer.affineTransform=transform;
  • 混合变换:

在一个变换的基础上做更深层次的变换,如做一个既要缩放又要旋转的变换,使用以下3个函数:

    1. CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
    2. CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
    3. CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)
    • 实现过程中一般先生成一个CGAffineTransform类型的空值,通过CGAffineTransformIdentity()函数获取
    • 如果需要混合两个已经存在的变换矩阵,就可以使用如下方法,在两个变换的基础上创建一个新的变换:
    • CGAffineTransform totalAffineTransform=CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);
      • 使用例子:
      • //实现先缩小50%,再旋转30度,最后向右移动200个像素
      • CGAffineTransform transform=CGAffineTransformIdentity;
      • transform=CGAffineTransformScale(transform,0.5,0.5);
      • transform=CGAffineTransformRotate(transform, M_PI / 180.0 * 30.0);
      • transform = CGAffineTransformTranslate(transform, 200, 0);
      • myView.layer.affineTransform=transform;

注意:

当你按顺序做了变换,上一个变换的结果将会影响之后的变换,所以200像素的向右平移同样也被旋转了30度,缩小了50%,所以它实际上是斜向移动了100像素

意味着变换的顺序会影响最终的结果,也就是说旋转之后的平移和平移之后的旋转结果可能不同

  • 剪切变换:

如一个矩形变成了一个平行四边形(倾斜)

    • 使用例子:
    • CGAffineTransform transform=CGAffineTransformIdentity;
    • transform.c=-1.0f;
    • transform.b=0f;
    • myView.layer.affineTransform=transform;
  • 3D变换:
    • transform属性
      • 是一个CATransform3D类型,UIView上没有对应属性
      • CG前缀属于Core Graphics框架(2D绘图API),CGAffineTransform仅对2D变换有效
      • 系统提供创建CATransform3D实例对象的主要3个方法:(对比Core Graphics的2D函数多出z轴参数)
      1. CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z);
      2. CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz) ;
      3. CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz);
        • 使用例子:
        • CATransform3D transform=CATransform3DMakeRotation(M_PI_4,0,1,0);
        • myView.layer.transform=transform;
        • 注意:若不设置透视投影效果,视图看起来没有斜向视角效果
  • 透视投影:
    • CATransform3D的m34属性用来做透视
      • m34默认值为0
      • 通过设置m34为-1.0/d应用透视效果,d代表视角与事物距离,通常设置为500-1000
      • 使用例子:
      • CATransform3D transform=CATransform3DIdentity;
      • transform.m34=-1.0/500.0;
      • transform=CATransform3DRotate(transform,M_PI_4,0,1,0);
      • myView.layer.transform=transform;
  • sublayerTransform属性:
    • 是一个CATransform3D类型,设置该属性会影响到所有的子图层,一次性对包含这些图层的容器做变换,所有子图层自动继承该变换方法
      • 使用例子:
      • [myContainerView addSubView:myView1];
      • [myContainerView addSubView:myView2];
      • CATransform3D perspective=CATransform3DIdentity;
      • perspective.m34=-1.0/500.0;
      • myContainerView.layer.sublayerTransform=perspective;
      • CATransform3D transform1 = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
      • myView1.layer.transform=transform1;
      • CATransform3D transform2=CATransform3DMakeRotation(-M_PI_4,0,1,0);
      • myView2.layer.transform=transform2;
  • 背面:
    • 默认图层是双面绘制,反面显示的是正面的一个镜像图片(不需要的时候会造成资源浪费)
    • 通过设置CALayer上的doubleSided属性为NO不绘制背面寄宿图内容
  • 扁平化图层:
    • 内部图层相对外部图层做了相反的变换,那么这两个变换将被相互抵消(绕Z轴做的变换);
      • 如:
      • CATransform3D outer = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
      • outerView.layer.transform = outer;
      • CATransform3D inner = CATransform3DMakeRotation(-M_PI_4, 0, 0, 1);
      • innerView.layer.transform = inner;
    • 若不是绕Z轴做的变换,而是Y轴,那么由于每个图层的3D场景是扁平化的,也就是有图层模拟出来的立体场景,倾斜时,子图层仍是被扁平贴在父视图上,父子层面永远平行,此时两相反变化没有呈现抵消效果
      • 如:
      • CATransform3D outer = CATransform3DIdentity;
      • outer.m34 = -1.0 / 500.0;
      • outer = CATransform3DRotate(outer, M_PI_4, 0, 1, 0);
      • self.outerView.layer.transform = outer;
      • CATransform3D inner = CATransform3DIdentity;
      • inner.m34 = -1.0 / 500.0;
      • inner = CATransform3DRotate(inner, -M_PI_4, 0, 1, 0);
      • self.innerView.layer.transform = inner;
  • 固体对象:
    • 固态的3D对象,实际上是一个技术上所谓的空洞对象,但整体以固态呈现
    • 用几面图层经位移旋转拼凑而成的固体,如使用例子:
      • @interface ViewController ()
      • @property (nonatomic, weak) IBOutlet UIView *containerView;
      • @property (nonatomic, strong) IBOutletCollection(UIView) NSArray *faces;
      • @end
      • @implementation ViewController
      • - (void)addFace:(NSInteger)index withTransform:(CATransform3D)transform{
      • //get the face view and add it to the container
      • UIView *face = self.faces[index];
      • [self.containerView addSubview:face];
      • //center the face view within the container
      • CGSize cOntainerSize= self.containerView.bounds.size;
      • face.center = CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);
      • // apply the transform
      • face.layer.transform = transform;
      • }
      • - (void)viewDidLoad{
      • [super viewDidLoad];
      • //set up the container sublayer transform
      • CATransform3D perspective = CATransform3DIdentity;
      • perspective.m34 = -1.0 / 500.0;
      • perspective = CATransform3DRotate(perspective, -M_PI_4, 1, 0, 0);
      • perspective = CATransform3DRotate(perspective, -M_PI_4, 0, 1, 0);
      • self.containerView.layer.sublayerTransform = perspective;
      • //add cube face 1
      • CATransform3D transform = CATransform3DMakeTranslation(0, 0, 100);
      • [self addFace:0 withTransform:transform];
      • //add cube face 2
      • transform = CATransform3DMakeTranslation(100, 0, 0);
      • transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
      • [self addFace:1 withTransform:transform];
      • //add cube face 3
      • transform = CATransform3DMakeTranslation(0, -100, 0);
      • transform = CATransform3DRotate(transform, M_PI_2, 1, 0, 0);
      • [self addFace:2 withTransform:transform];
      • //add cube face 4
      • transform = CATransform3DMakeTranslation(0, 100, 0);
      • transform = CATransform3DRotate(transform, -M_PI_2, 1, 0, 0);
      • [self addFace:3 withTransform:transform];
      • //add cube face 5
      • transform = CATransform3DMakeTranslation(-100, 0, 0);
      • transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);
      • [self addFace:4 withTransform:transform];
      • //add cube face 6
      • transform = CATransform3DMakeTranslation(0, 0, -100);
      • transform = CATransform3DRotate(transform, M_PI, 0, 1, 0);
      • [self addFace:5 withTransform:transform];
      • }
      • @end
  • 光亮与阴影:
    • 可以通过改变每个面的背景颜色或者直接用带光亮效果的图片来调整
    • 用GLKit框架来做向量的计算(略)
  • 点击事件:
    • 点击事件的处理由视图在父视图中的顺序决定的,并不是3D空间中的Z轴顺序
    • 当立体显示视图时因响应顺序问题导致事件拦截的问题,解决方案:
    • 把除了表面的其他视图userInteractionEnabled属性都设置成NO来禁止事件传递。
    • 或者简单通过代码把视图覆盖在拦截了事件的视图上。

iOS Core Animation Advanced Techniques-变换


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
author-avatar
手机用户2502917387
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有