CoreAnimation图层的树状结构和寄宿图
1.图层的树状结构
Core Animation的前身叫做Layer Kit,所以,你应该意识到Core Animation并不只是用来做动画的。做动画只是Core Animation特性的冰山一角。
Core Animation是一个复合引擎,他的职责就是尽可能的组合屏幕上不同的可视类容,这个内容是被分解成独立的图层,存储在一个叫做图层树的体系之中。
这个树形成了UIKit以及在iOS应用程序中你所能在屏幕上看见的一切的基础。
视图:
一个视图就是屏幕上显示的一个矩形块(比如图片,文字或者视频),它能够拦截类似鼠标点击或者触摸手势等用户输入。视图的层级关系中可以互相嵌套,一个视图可以管理它的所有子视图。
在iOS中,所有的视图都从一个叫做UIView的基类派生而来,UIView可以处理触摸事件,可以支持基于Core Graphics绘图,可以做仿射变换(例如旋转或者缩放),或者简单的类似于滑动或者渐变的动画。
图层:
CALayer类在概念上和UIView类似,同样也是一些被层级关系树管理的矩形块,同样也包含一些内容(图片、文字或者背景色),能管理所有子图层的位置。图层有一些方法和属性来做动画和变换。和UIView最大的不同是CALayer不处理用户交互,因为CALayer并不清楚具体的相应链(iOS通过视图层级关系用来传送触摸事件的机制)。但是图层提供了一些方法来判断是否一个触点在图层的范围之内。
小结:UIView可以说就是CALayer的代理,视图的职责就是创建并管理它对应的图层,以确保子视图在层级关系中添加或者被移除的时候,他们关联的图层也同样在对应的层级关系树当中有相同的操作。
CALayer的能力:
对于一些简单的需求来说,我们没必要处理CALayer。因为苹果已经通过UIView的高级API间接地使动画变得很简单。但是UIView是对CALayer的封装,这使得UIView的灵活性远远低于CALayer。如下是UIView没有暴露出来的CALayer的功能:
1.阴影、圆角、带颜色的边框
2.3D变换
3.非矩阵范围
4.透明遮罩
5.多级非线性动画
说明:使用图层需要导入QuartzCore框架。我们一般的情况下添加UIView的时候附带添加了其对应的CALayer。我们也可以只在UIView上添加CALayer。
某些特殊情况下更需要使用CALayer:
1.开发同时可以在Mac OS上运行的跨平台应用
2.使用多种CALayer的子类,并且不想创建UIView去包装它们
3.做一些对性能特别挑剔的工作,比如对UIView一些可以忽略不计的操作都会引起显著的不同。
---------------------------
2.寄宿图(CALayer包含的图)
属性:
contents:
该属性被定义为id,但是只能给它赋CGImageRef类型的值,因为跨平台的问题(在Mac OS系统上,这个属性对CGImage和NSImage类型的值都有用)。UIImage有个CGImage属性类型是CGImageRef。但是CGImageRef并不是一个Cocoa对象,而是一个Core Foundation类型,所以必须使用桥接来赋值。
eg: layer.contents = (_bridge id)image.CGImage;
------------
contentGravity:
其实这个属性对应的就是UIView里面的contentMode属性。用法差不多,contentMode对应着一个枚举,contentGravity对应着NSString。
eg: self.layerView.layer.contentsGravity = kCAGravityResizeAspect;对应着aspectFit
说明:kCAGravityResizeAspect并不会考虑分辨率的问题,它就是拉伸图片以适应图层而已。
------------
contentScale:
这个属性并不是一直有用,比如将contentGravity设置为了kCAGravityResizeAspect,那么设置contentScale属性是没用的。但是如果你设置其为kCAGravityCenter(不会拉伸图片),那就有效果了。
contentScale属性属于支持高分辨率屏幕机制的一部分。如果设置为1那么代表每个点一个像素来绘制图片,如果设置为2那么就代表每个点2*2个像素来绘制图片。
相比较于UIImage,CGImage没有拉伸的概念。当你设置kCAGravityResizeAspect的时候其实就是强行拉伸了,所以设置contentScale没有用。所以使用CGImage来设置图层的内容,并且不拉伸的时候,一般带上这句话:
eg:
self.layerView.layer.contentsScale = image.scale;
或者
self.layerView.layer.contentsScale =
[UIScreen mainScreen].scale
;
--------------
maskToBounds:
对比到UIView就是clipsToBounds属性。决定超出边界的内容是否显示。
---------------
contentRect:
CALayer的contentRect属性容许我们显示图层框内的寄宿图的局部,这涉及到图片是如何显示和拉伸的,所以要比contentGravity灵活很多。和bounds、frame不同,contentRect采用了单位坐标(值在0~1),是一个相对值(像素和点都是绝对值)。所以contentRect是相对于寄宿图的尺寸的。
eg: layer.contentRect = CGRectMake(0, 0, 0,5, 0.5);
iOS使用的坐标系统:
1.点--在iOS和Mac OS中最常见的坐标体系。点就像是虚拟的像素,也被称作逻辑像素。在标准设备上,一个点就是一个像素,但是在Retina设备上,一个点等于2*2个像素。iOS用点作为屏幕的坐标测算体系就是为了在Retina设备和普通设备上能有一致的视觉效果。
2.像素 —— 物理像素坐标并不会用来屏幕布局,但是仍然与图片有相对关系。UIImage是一个屏幕分辨率解决方案,所以指定点来度量大小。但是一些底层的图片表示如CGImage就会使用像素,所以你要清楚在Retina设备和普通设备上,他们表现出来了不同的大小。
3. 单位 —— 对于与图片大小或是图层边界相关的显示,单位坐标是一个方便的度量方式, 当大小改变的时候,也不需要再次调整。单位坐标在OpenGL这种纹理坐标系统中用得很多,Core Animation中也用到了单位坐标。
关于contentRect属性的一个很有意思的用法--(图片拼接)
规则:像平常一样载入我们的大图,然后把它赋值给四个独立的图层的contents,然后设置每个图层的contentsRect来去掉我们不想显示的部分
- (void)addSpriteImage:(UIImage *)image withContentRect:(CGRect)rect toLayer:(CALayer *)layer {
<pre name="code" class="objc">//set image
layer.contents = (__bridge id)image.CGImage;
<pre name="code" class="objc">//scale contents to fit
layer.contentsGravity = kCAGravityResizeAspect;
//set contentsRect
layer.contentsRect = rect;
}
- (void)viewDidLoad
{[super viewDidLoad]; //load sprite sheetUIImage *image = [UIImage imageNamed:@"Sprites.png"];//加载拼接图片//set igloo sprite[self addSpriteImage:image withContentRect:CGRectMake(0, 0, 0.5, 0.5) toLayer:self.iglooView.layer];//gei//set cone sprite[self addSpriteImage:image withContentRect:CGRectMake(0.5, 0, 0.5, 0.5) toLayer:self.coneView.layer];//set anchor sprite[self addSpriteImage:image withContentRect:CGRectMake(0, 0.5, 0.5, 0.5) toLayer:self.anchorView.layer];//set spaceship sprite[self addSpriteImage:image withContentRect:CGRectMake(0.5, 0.5, 0.5, 0.5) toLayer:self.shipView.layer];
}
拼合不仅给app提供了一个整洁的载入方式,还有效地提高了载入性能(单张大图比多张小图载入地更快),但是如果有手动安排的话,他们还是有一些不方便的,如果你需要在一个已经创建好的品和图上做一些尺寸上的修改或者其他变动,无疑是比较麻烦的。
Mac上有一些商业软件可以为你自动拼合图片,这些工具自动生成一个包含拼合后的坐标的XML或者plist文件,拼合图片的使用大大简化。这个文件可以和图片一同载入,并给每个拼合的图层设置contentsRect,这样开发者就不用手动写代码来摆放位置了。
这些文件通常在OpenGL游戏中使用,不过呢,你要是有兴趣在一些常见的app中使用拼合技术,那么一个叫做LayerSprites的开源库(https://github.com/nicklockwood/LayerSprites),它能够读取Cocos2D格式中的拼合图并在普通的Core Animation层中显示出来。
------------------------
contentsCenter:
contentsCenter其实是一个Rect,它定义了一个固定的边框和一个在图层上可拉伸的区域。改变contentsCenter的值并不会影响到寄宿图的显示,除非这个图层的大小改变了,才看得到效果。现在一个图层的大小是100*100,放一张100*100的图片上去,然后设置contentRect,显示图片的局部,但是图层的大小没变,此时图片就有了拉伸,此时再去设置contentsCenter就会有效果,前提是图片一定是拉伸了。
CGImageRef image = [UIImage imageNamed:@"3"].CGImage;UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];btn.frame = CGRectMake(20, 20, CGImageGetWidth(image), CGImageGetHeight(image));;btn.layer.contents = (__bridge id)image;btn.layer.contentsRect = CGRectMake(0.25, 0.25, 0.5, 0.5);btn.layer.contentsCenter = CGRectMake(0.33, 0.33, 0.33, 0.33);btn.layer.contentsGravity = kCAGravityResize;self.btn1 = btn;[self.view addSubview:self.btn1];
原图:
下面是局部显示的原图,上面是利用contentsCenter处理后的图片
说明:在SB里面有个Stretching就是用来设置contetsCenter的。
步骤:在SB上面拖一个Btn,选属性下面就看到了
CoreAnimation图层的树状结构和寄宿图相关推荐
- 用中值排序基数法实现树状结构 (转)
在BBS的编写中,经常有人问怎样实现树状结构?一个比较不负责任的回答是:使用递归算法.当然,递归是一个可行的办法 (二叉树的历遍也好象只能使用递归算法),但对于BBS来说,这样做势必要进行大量的Sql ...
- 递归查询树状结构某个确定的节点
递归 递归算法在日常工作中算是用的比较多的一种,比如DOM树的遍历,多层级树状结构的生成,遍历寻找某个树节点等 1 先来看下数据结构 var result = {id:0,name:"张飞& ...
- 系统管理模块_部门管理_设计(映射)本模块中的所有实体并总结设计实体的技巧_懒加载异常问题_树状结构...
系统管理模块_部门管理_设计本模块中的所有实体并总结设计实体的技巧 设计实体流程 1,有几个实体? 一般是一组增删改查对应一个实体. 2,实体之间有什么关系? 一般是页面引用了其他的实体时,就表示与这 ...
- file类打印目录---树状结构,递归
package Test; import java.io.File; /** * file类打印目录---树状结构,递归 * @author Administrator * */ public cla ...
- oracle 树状结构一直出现不了_SEO站内优化:网站结构优化(十一)
上文已经对搜索引擎排名机制,以及影响关键词排名的因素进行了全面的讲解,详情查阅SEO入门到精通(十):搜索引擎的排名机制.本文主要讲解站内优化中最为重要的"网站结构优化",为什么说 ...
- oracle 树状结构一直出现不了_深入解析Oracle ASSM 段头块(PAGETABLE SEGMENT HEADER)结构...
一.概念介绍 Oracle ASSM(Automatic Segment Space Managed)使用位图来管理数据库中的空间,具有管理简单.高并发等优点,ASSM的整体结构是3层位图块+数据块, ...
- 我的前端工具集(四)树状结构后篇
我的前端工具集(四)树状结构后篇 liuyuhang原创,未经允许禁止转载 目录 我的前端工具集 上文连接 我的前端工具集(四)树状结构前偏 1.数据组织 在3.2.节有截图 2.树状结构代码 2 ...
- 数据库树状结构的关系表的删除方案
所谓的树状结构的关系,即是记录之间有id,parentId关系的数据.场景是这样的:业务中用到了一张分享表,表里的主要字段有分享人,和被分享人,以及分享任务ID,可以通过一系列的分享构造成树状的结构, ...
- 使用jQuery Treeview插件实现树状结构效果
首先到一个国外网站上下载Treeview插件: http://bassistance.de/jquery-plugins/jquery-plugin-treeview/ 当然你也可以通过我博客的源文件 ...
最新文章
- 2020 中国高校薪资排行出炉!好过双一流的高校原来这么多!
- linux cache控制 内核,linux内核之bcache简介 [转]
- Java Web开发入门 - 第5章 Git
- 如何让服务器运行js,服务器端JavaScript运行环境Node.js的依赖性管理
- Interview:算法岗位面试—11.05下午上海某银行信息(总行,四大行之一)技术岗笔试记录
- 【Python】创建、保存、复制虚拟环境 venv
- 剑指offer(21):栈的压入、弹出序列
- 习惯的力量之五让迟延见鬼去吧
- 同步方法中的锁对象_互斥锁与读写锁:如何使用锁完成Go程同步?
- php session 跨子域,PHP session 跨子域问题总结
- 谈一下“男”字“,女”字,怎样解析?
- java基础:8.1 异常
- 区间dp讲解之石子合并问题 区间dp的分析方法
- 并发编程常见面试题总结三
- CMS:内容管理系统
- CSS 查看css兼容性的站点
- 华三(H3C)单臂路由
- SEM和SD的区别和联系,以及其计算方法(实际作图方法)
- 微信也能设置主题了,盘他!
- 15张超详细的Python学习路线图,纯良心分享,零基础学习宝典
热门文章
- python量化0基础培训_【点宽学院】3周!0基础Python量化投资!闯关式学习打卡,解锁新技能!(第4期)...
- 组队学习爆火ChatGPT背后的基础知识!
- 有没有测试牙齿需不需要修正的软件,快来测试一下你的口腔是否健康
- 你绝对能看懂的Kafka源代码分析-RecordAccumulator类代码分析
- Windows查询计算机设备序列号、MAC地址和硬盘序列号
- ttshop是PHP开发的,讯想-B2B2C多用户商城系统
- VSCODE设置自动换行后仍然无法在视区宽度内自动换行
- KC2009正式版使用技巧四则
- 离散数学期末复习-等价关系和偏序关系
- 相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了!...