Core Animation

本文为读书笔记: iOS Core Animation: Advanced Techniques
1.实际上layer才是真正用来在屏幕上显示和做动画,UIView仅仅是对它的一个封装,提供了一些iOS类似于处理触摸的具体功能,以及Core Animation底层方法的高级接口。

2.我们已经证实了图层不能像视图那样处理触摸事件,那么他能做哪些视图不能做的呢?这里有一些UIView没有暴露出来的CALayer的功能:

  • 阴影 、圆角、带颜色的边框
  • 3D变换
  • 非矩形范围
  • 透明遮罩
  • 多级非线性动画
CALayer 属性 属性类型 作用
contents id 设置图片
contentsGravity NSString 设置图片展示,类似于viewcontentMode

3.contents

id意味着给contents赋任何值编译都可以通过,但是,在实践中,如果你给contents赋的不是CGImage,那么你得到的图层将是空白的。contents这个奇怪的表现是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImageNSImage类型的值都起作用。
使用 :layer.contents = (__bridge id)image.CGImage;

4.contentsGravity
UIViewcontentMode,对这些属性的操作其实是对对应图层的操作,contentsGravity就是图层的contentMode


/** Layer `contentsGravity' values. **/

CA_EXTERN NSString * const kCAGravityCenter

CA_EXTERN NSString * const kCAGravityTop

CA_EXTERN NSString * const kCAGravityBottom

CA_EXTERN NSString * const kCAGravityLeft

CA_EXTERN NSString * const kCAGravityRight

CA_EXTERN NSString * const kCAGravityTopLeft

CA_EXTERN NSString * const kCAGravityTopRight

CA_EXTERN NSString * const kCAGravityBottomLeft

CA_EXTERN NSString * const kCAGravityBottomRight

CA_EXTERN NSString * const kCAGravityResize

CA_EXTERN NSString * const kCAGravityResizeAspect

CA_EXTERN NSString * const kCAGravityResizeAspectFill

5.contentsScale这个设置图片的每个点1个像素或者两个像素
使用 :
layer.contentsScale = image.scale;
或者
layer.contentsScale = [UIScreen mainScreen].scale;
6.contentsRect 可以用来作拼合图片(一般APP估计不会使用)
7.CALayer给不同坐标系之间的图层转换提供了一些工具类方法:

- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer; 
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer; 
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
 - (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;

8.阴影效果

  • shadowOpacity : 是一个必须在0.0(不可见)和1.0(完全不透明)之间的浮点数。
  • shadowColor : 属性控制着阴影的颜色,和borderColorbackgroundColor一样,它的类型也是CGColorRef。阴影默认是黑色。
  • shadowOffset属性控制着阴影的方向和距离。它是一个CGSize的值,宽度控制这阴影横向的位移,高度控制着纵向的位移。shadowOffset的默认值是 {0, -3},意即阴影相对于Y轴有3个点的向上位移(以为shadow最早出现在MacOS,在MacOS上坐标轴和iOS是相反的)。
  • shadowPath : 如果事先知道阴影的形状,可以设置shadowPath来提高性能。

9.opacity相当于viewalpha

10.layer.shouldRasterize
这是由透明度的混合叠加造成的,当你显示一个50%透明度的图层时,图层的每个像素都会一半显示自己的颜色,另一半显示图层下面的颜色。这是正常的透明度的表现。但是如果图层包含一个同样显示50%透明的子图层时,你所看到的视图,50%来自子视图,25%来了图层本身的颜色,另外的25%则来自背景色。
在我们的示例中,按钮和表情都是白色背景。虽然他们都是50%的可见度,但是合起来的可见度是75%,所以标签所在的区域看上去就没有周围的部分那么透明。所以看上去子视图就高亮了,使得这个显示效果都糟透了。
解决办法:

bottomView.layer.shouldRasterize = YES;  
bottomView.layer.rasterizationScale = [UIScreen mainScreen].scale;

11.CGAffineTransform

  • 仿射的意思是无论变换矩阵用什么值,图层中平行的两条线在变换之后任然保持平行
  • 如果需要混合两个已经存在的变换矩阵,就可以使用如下方法,在两个变换的基础上创建一个新的变换:
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);

12.CATransform3Dm34元素,用来做透视
详见

- (void)viewDidLoad {    [super viewDidLoad];  
  //create a new transform    
CATransform3D transform = CATransform3DIdentity;   
 //apply perspective  
  transform.m34 = - 1.0 / 500.0;  
  //rotate by 45 degrees along the Y axis  
  transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);   
 //apply to layer    
self.layerView.layer.transform = transform; }
  1. 创建一个3D的正方体](https://zsisme.gitbooks.io/ios-/content/chapter5/solid-objects.html))
    14.Core Graphics直接向原始的CALyer的内容中绘制一个路径,相比直下,使用CAShapeLayer有以下一些优点:
  • 渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。
  • 高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。
  • 不会被图层边界剪裁掉。一个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉(如我们在第二章所见)。
  • 不会出现像素化。当你给CAShapeLayer做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。

15.UILabel : 借助图层代理直接将字符串使用Core Graphics写入图层的内容
16.宿主图层 : 指的是viewlayer,既self.view.layer,可以通过下面的方法改变


+ (Class)layerClass

{

    return [CATextLayer class];

}

17.CATextLayer替换 UILabal](https://zsisme.gitbooks.io/ios-/content/chapter6/CATextLayer.html))

18.CATransformLayer :创建一个立方体图层
19.CAGradientLayer

  • colors : 保存的各种颜色
  • locations : 颜色的作用范围,这个范围数组需要个颜色数组保持相同 , 当只有两个颜色的时候设置gradientLayer.locations = @[@0,@1];是均分两个视图
  • startPoint,开始的点,(0 , 0)代表左上角
  • endPoint,结束的店,(1 , 1)代表右下角

20.CATiledLayer : 把一个大图裁剪成小图并加载,一般用在地图,或者加载大的图片.

  1. Transactions(事务) : 实际上是Core Animation用来包含一系列属性动画集合的机制,任何用指定事务去改变可以做动画的图层属性都不会立刻发生变化,而是当事务一旦提交的时候开始用一个动画过渡到新值。
  • begin : 开始
  • commit : 结束
  • + (void)setCompletionBlock:(nullable void (^)(void))block; : 代码完成块

例1

- (void)viewDidLoad

{

    [super viewDidLoad];    

    self.colorLayer = [CALayer layer];

    self.colorLayer.frame = CGRectMake(0.0f, 0.0f, 150.0f, 150.0f);

    self.colorLayer.backgroundColor = [UIColor blueColor].CGColor;

    //add it to our view

    [self.containerView.layer addSublayer:self.colorLayer];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{
   //begin a new transaction

    [CATransaction begin];

    //set the animation duration to 1 second

    [CATransaction setAnimationDuration:5.0];

    //randomize the layer background color

    CGFloat red = arc4random() / (CGFloat)INT_MAX;

    CGFloat green = arc4random() / (CGFloat)INT_MAX;

    CGFloat blue = arc4random() / (CGFloat)INT_MAX;

    self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;

    //commit the transaction

    [CATransaction commit];

}

例2

- (void)viewDidLoad{    [super viewDidLoad];    //create sublayer    self.colorLayer = [CALayer layer];    self.colorLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);    self.colorLayer.backgroundColor = [UIColor blueColor].CGColor;    //add a custom action    CATransition *transition = [CATransition animation];    transition.type = kCATransitionPush;    transition.subtype = kCATransitionFromLeft;    self.colorLayer.actions = @{@"backgroundColor": transition};    //add it to our view    [self.layerView.layer addSublayer:self.colorLayer];}- (IBAction)changeColor{    //randomize the layer background color    CGFloat red = arc4random() / (CGFloat)INT_MAX;    CGFloat green = arc4random() / (CGFloat)INT_MAX;    CGFloat blue = arc4random() / (CGFloat)INT_MAX;    self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;}

22.隐式动画是如何实现的

  • 图层首先检测它是否有委托,并且是否实现CALayerDelegate
    协议指定的-actionForLayer:forKey
    方法。如果有,直接调用并返回结果。
  • 如果没有委托,或者委托没有实现-actionForLayer:forKey
    方法,图层接着检查包含属性名称对应行为映射的actions
    字典。
  • 如果actions字典
    没有包含对应的属性,那么图层接着在它的style
    字典接着搜索属性名。
  • 最后,如果在style
    里面也找不到对应的行为,那么图层将会直接调用定义了每个属性的标准行为的-defaultActionForKey:
    方法。

23.CATransition响应CAAction协议,并且可以当做一个图层行为.行为通常是一个被Core Animation隐式调用的显式动画对象。

24.presentationLayer : 呈现图层 ,用户真正看到的图层(相当于View)
modelLayer : 图层模型 (相当于Model)
Core Animation : 相当于控制器

大多数情况下,你不需要直接访问呈现图层,你可以通过和模型图层的交互,来让Core Animation更新显示。两种情况下呈现图层会变得很有用,一个是同步动画,一个是处理用户交互。

  • 如果你在实现一个基于定时器的动画(见第11章“基于定时器的动画”),而不仅仅是基于事务的动画,这个时候准确地知道在某一时刻图层显示在什么位置就会对正确摆放图层很有用了。
  • 如果你想让你做动画的图层响应用户输入,你可以使用-hitTest:方法(见第三章“图层几何学”)来判断指定图层是否被触摸,这时候对呈现图层而不是模型图层调用-hitTest:会显得更有意义,因为呈现图层代表了用户当前看到的图层位置,而不是当前动画结束之后的位置。

25.缓冲函数CAMediaTimingFunction
自定义缓冲函数

+ (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;

- (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
  • 那么该如何使用缓冲方程式呢?
    首先需要设置CAAnimation的timingFunction属性,是CAMediaTimingFunction类的一个对象。如果想改变隐式动画的计时函数,同样也可以使用CATransaction+setAnimationTimingFunction:方法。

26.RunLoop

NSDefaultRunLoopMode - 标准优先级
NSRunLoopCommonModes- 高优先级
UITrackingRunLoopMode- 用于UIScrollView和别的控件的动画

CADisplayLink : 屏幕更新执行一次刷新一次

self.timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)]; 
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];

NSTimer :标准的时间


self.timer = [NSTimer timerWithTimeInterval:1/60.0                                 target:self                               selector:@selector(step:)                               userInfo:nil                                repeats:YES];[[NSRunLoop mainRunLoop] addTimer:self.timer                          forMode:NSRunLoopCommonModes];

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容