###1、CALayer(图层类)的基本概括
- CALayer 是整个图层类的基础,它是所有核心动画图层类的父类。
- 和视图类(UIView)一样,CALayer 有自己的父图层类,同时也拥有自己子图层类的集合,它们构成了一个图层树的层次结构。
- CALayer 从 Application Kit 和 Cocoa Touch 的视图类分离出来。
- CALayer 类的内容显示可以通过以下方法提供:
1. 可以直接或者委托的方式把图层的内容属性设置为 Core Graphics image。
2. 提供直接绘制到一个 Core Graphics image 上下文委托。
3. 设置所有图层所具有的可视化样式属性,比如背景颜色、不透明属性、蒙版、边框、圆角等。
4. CAScrollLayer 是 CALayer 的子类,简化显示图层的一部分内容。CAScrollLayer 对象的滚动区域的范围在它的子图层里面定义。CAScrollLaye 不提供键盘或鼠标事件处理,也不提供可见的滚动条。
5. CATextLayer 可以方便的从字符串或字符串的内容创建一个图层类的内容。
6. CATiledLayer 允许递增的显示大而复杂的图片。
7. CAEAGLLayer 提供了一个OpenGLES渲染环境。
- CALayer 的还扩展了 NSKeyValueCoding 的非正式协议,加入默认键值和额外的结构类型的自动对象包装 (CGPoint,CGSize,CGRect,CGAffineTransform 和 CATransform3D)的支持,并 提供许多这些结构的关键路径领域的访问。
- CALayer 同时管理与层关联的动画和行为。图层接受层树的插入和删除层动作, 修改层的属性,或者明确的开发请求。这些行为通常会导致动画发生
(隐式动画)
。 - 虽然核心动画的图层和 Cocoa 的视图在很大程度上没有一定的相似性,但是他们两者**
最大的区别是,图层不会直接渲染到屏幕上。
** - 在模型-视图-控制器(model-view-controller)概念里面 NSView 和 UIView 是典 型的视图部分,但是在核心动画里面图层是模型部分。图层封装了几何、时间、可视 化属性,同时它提供了图层现实的内容,但是实际显示的过程则不是由它来完成。
- 每个可见的图层树由两个相应的树组成:一个是呈现树,一个是渲染树。
- 呈现树:呈现树包含了当前动画发生时候将要显示的值,例如你要给图层背景颜色设置新 的值的时候,它会立即修改图层树里面相应的值。但是在呈现树里面背景颜色值在将 要显示给用户的时候才被更新为新值。
- 渲染数:渲染树在渲染图层的时候使用呈现树的值。渲染树负责执行独立于应用活动的复 杂操作。渲染由一个单独的进程或线程来执行,使其对应用程序的运行循环影响最小。
###2、图层树
- 图层树是核心动画里面类似 Cocoa 视图的层次结构,一个核心动画的图层拥有父图层(suplayer)和子图层(sublayer)。
- 核心动画不提供在一个窗口(window)实际显示图层的手段,它们必须通过视图来托管。
当视图和图层一起的时候,视图为图层提供了底层的事件处理,而图层为视图提供了显示的内容
。 - iOS 上面的视图系统直接建立在核心动画的图层上面。每个 UIView 的实例会自动的创建一个 CALayer 类的实例,然后把该实例赋值给视图的 layer 属性。
/*1、每一个UIView都会有一个layer。
2、将layer添加到父layer中,self.view.layer为父图层,layer为子图层。
*/
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(100, 100, 200, 200);
layer.backgroundColor = [UIColor blueColor].CGColor;
[self.view.layer addSublayer:layer];
###3、给CALayer提供内容 你可以通过以下任何一种方法指定 CALayer 实例的内容:
- 使用包含图片内容的
CGImageRef
来显式的设置图层的 contents 的属性。 - 使用CALayer的子类填充内容。
- 指定一个委托,它提供或者重绘内容。
- 继承 CALayer 类重载显示的函数。
- 设置contents属性
// 给layer添加图片内容
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = CGRectMake(50, 100, 200, 200);
imageLayer.backgroundColor = [UIColor lightGrayColor].CGColor;
UIImage *image = [UIImage imageNamed:@"心.png"];
imageLayer.contents = (__bridge id)(image.CGImage);
[self.view.layer addSublayer:imageLayer];
- 使用CALayer的子类填充内容
// 填充文字的layer:CATextLayer
CATextLayer *textLayer = [CATextLayer layer];
textLayer.frame = CGRectMake(50, 400, 200, 30);
textLayer.foregroundColor = [UIColor redColor].CGColor;
textLayer.backgroundColor = [UIColor lightGrayColor].CGColor;
textLayer.string = @"这是填充文字的leyer";
textLayer.fontSize = 20;
textLayer.font = (__bridge CFTypeRef )(@"楷体");
textLayer.alignmentMode = kCAAlignmentCenter;
[self.view.layer addSublayer:textLayer];
- 通过创建一个委托类实现下列方法之一:
displayLayer:
或drawLayer:inContext:
。通过发送以下任何一个方法setNeedsDisplay
或 者setNeedsDisplayInRect:
的消息, 或者把图层的needsDisplayOnBoundsChange
属性值设置为 YES。
- (void)viewDidLoad {
[super viewDidLoad];
CALayer *drawLayer = [CALayer layer];
drawLayer.frame = CGRectMake(50, 400, 200, 200);
[self.view.layer addSublayer:drawLayer];
drawLayer.delegate = self;
[drawLayer setNeedsDisplay]; // 重绘
}
// CALayer的代理方法<CALayerDelegate>
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
// 画矩形
CGRect rect = CGRectMake(50, 0, 100, 50);
CGContextSetRGBFillColor(ctx, 0.1, 0.5, 0.5, 1);
CGContextSetRGBStrokeColor(ctx, 1.0, 0.1, 0.1, 1);
CGContextAddRect(ctx, rect);
CGContextDrawPath(ctx, kCGPathFillStroke);
}
- 通过子类提供图层的内容,你的图层需要定制行为而委托又无法满足需求的时候。子类可以重载 CALayer 的显示方法,设置图层的内容为适当的图片。
###4、修改图层内容的位置 CALayer 的属性 contentsGravity
允许你在图层的边界内容修改图层的 contents 图片的位置或者伸缩值。默认情况下,内容的图像完全填充层的边界,忽视自然的图像宽高比。
相应填充的位置:
1. kCAGravityTopLeft // 左上
2. kCAGravityTop // 顶部
3. kCAGravityTopRight // 右上
4. kCAGravityLeft // 左
5. kCAGravityCenter // 中心
6. kCAGravityRight // 右
7. kCAGravityBottomLeft // 左下
8. kCAGravityBottom // 下
9. kCAGravityBottomRight // 右下
10.kCAGravityResize // 拉伸
11.kCAGravityResizeAspect // 等比例
12.kCAGravityResizeAspectFill // 完全填充
###5、图层样式属性
- 几何属性:
-
frame
-
bounds
-
position
-
anchorPoint
-
cornerRadius
-
transform
-
zPosition
- 背景属性:
-
backgroundColor
- backgroundFilters --滤镜(iOS不可用)
- 图层内容:
contents
- 子图层内容:
-
sublayers
-
masksToBounds
-
sublayerTransform
- 边框属性:
-
borderColor
-
borderWidth
- 滤镜属性:
- filters(iOS不可用)
- 阴影属性:
-
shadowColor
-
shadowOffset
-
shadowOpacity
-
shadowRadius
- 不透明属性:
opacity
- 混合属性:
- compositingFilter -- 混合滤镜(iOS不可用)
- 遮罩属性:
mask
CALayer *pLayer = [CALayer layer];
[self.view.layer addSublayer:pLayer];
//坐标尺寸、背景颜色
pLayer.frame = CGRectMake(50, 100, 200, 200);
pLayer.backgroundColor = [UIColor lightGrayColor].CGColor;
//内容
pLayer.contents = (__bridge id)[UIImage imageNamed:@"image.jpg"].CGImage;
pLayer.contentsGravity = kCAGravityResize;
// 圆角
pLayer.cornerRadius = 20;
pLayer.masksToBounds = YES; // 必须设为YES圆角才起作用
// 边框
pLayer.borderColor = [UIColor blackColor].CGColor;
pLayer.borderWidth = 5;
// 阴影
pLayer.shadowColor = [UIColor grayColor].CGColor;
pLayer.shadowOffset = CGSizeMake(5, 5);
pLayer.shadowOpacity = 1;
pLayer.shadowRadius = 10;
//透明度
pLayer.opacity = 0.5;
//坐标变换transform,缩放、旋转、移动
pLayer.transform = CATransform3DMakeScale(0.5, 0.5, 1);
pLayer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
pLayer.transform = CATransform3DMakeTranslation(0, 50, 0);
//KVC设置transform
[pLayer setValue:@0.5 forKeyPath:@"transform.scale"];
[pLayer setValue:@1.0 forKeyPath:@"transform.scale.x"];
[pLayer setValue:@M_PI_4 forKeyPath:@"transform.rotation"];
[pLayer setValue:@50 forKeyPath:@"transform.translation.y"];
###6、图层的行为(隐式动画)
- 图层的行为在以下情况发生的时候被触发:从图层树里面插入或者删除一个图层,图层的属性值被修改了,或者程序显式要求。通常情况下,行为触发器是动画显示的结果所在。
- 一个行为对象是一个通过
CAAction
协议响应行为标识符的对象。行为标识符使 用标准圆点分隔的关键路径来命名。图层负责把行为标识符映射到特定的行为对象。 当一个特定标识符的行为对象被确定的时候,它会发送一个 CAAction 协议定义的消息。 - CALayer类提供了默认的CAAnimation的行为对象实例,一个兼容类所有动画层属性CAAction协议。
- CALayer类提供了默认的CAAnimation的行为对象实例,一个兼容类所有动画层属性CAAction协议。
// 当改变layer属性值得时候,会自动产生一个动画,这个动画叫隐式动画
pLayer.opacity=0.0;
pLayer.position=CGPointMake(0.0,0.0);
pLayer.transform = CATransform3DMakeScale(0.5, 0.5, 1);
###7、事务 图层的每个改变都是事务的一部分。CATransaction
是核心动画类,它负责成批的把多个图层树的修改作为一个原子更新到渲染树。
- 隐式事务:
- 当图层树被没有获得事务的线程修改的时候将会自动创建隐式事务,当线程的运行循环(run-loop)执行下次迭代的时候将会自动提交事务。
- 重要:当在一个没有运行循环(
runloop
)的线程修改图层的属性的时候,你必须使用显式的事务。
- 显示事务:
- 在你修改图层树之前,可以通过给 CATransaction 类发送一个
begin
消息来创建一 个显式事务,修改完成之后发送comit
消息。 - 你可以在修改图层属性值的时候通过设置事务的
kCATransactionDisableActions
或者setDisableActions
值为 YES 来暂时禁用图层的行为。在事务范围所作的任何更改也不会因此而发生的动画。
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
//[CATransaction setDisableActions:YES];
[aLayer removeFromSuperlayer];
 [CATransaction commit]; ```
3. 可以暂时改变响应改变图层属性的动画的时间,通过设置事务的 `kCATransactionAnimationDuration`或者`setAnimationDuration` 键的值为新的时间。
```
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:10.0f]
forKey:kCATransactionAnimationDuration];
//[CATransaction setAnimationDuration:10.0f];
theLayer.zPosition=200.0;
theLayer.opacity=0.0;
[CATransaction commit];
```
- 事务嵌套:
显式事务可以被嵌套,允许你禁用部分动画的行为或者在属性被修改的时候产生 的动画使用不同的时间。仅当最外层的事务被提交的时候,动画才会发生。
[CATransaction begin];
[CATransaction setAnimationDuration:2];
pLayer.opacity = 0.0;
[CATransaction begin];
pLayer.transform = CATransform3DMakeScale(3, 3, 1);
[CATransaction commit];
[CATransaction commit];