CALayer简介和一些基本概念:
在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView.其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层.在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层.
Core Animation 是跨平台的,支持iOS环境和Mac OS X环境,在核心动画中,需要先理解CALayer,核心动画操作的对象不是UIView,而是CALayer.在使用Core Animation开发动画的本质就是将CALayer中的内容转化为位图从而供硬件操作.通过操作CALayer对象,可以很方便地调整UIView的一些外观属性.比如,可以做圆角、阴影、边框等效果.
图层和视图之间的关系:
1:创建视图对象时,视图会自己创建一个层,视图在绘图(如drawRect:)时,会将内容画在自己的层上。当视图在层上完成绘图后,系统会将图层拷贝至屏幕(换句话说,UIView本身不具备显示的功能,是它内部的层才有显示功能.)。每个视图都有一个层,而每个图层又可以有多个子层.
提示:
CALayer的设计目的不是为了取代视图,因此不能基于CALayer创建一个独立的可视化组件
CALayer的设计目的是提供视图的基本可视内容,从而提高动画的执行效率
除提供可视内容外,Layer不负责视图的事件响应、内容绘制等工作,同时Layer不能参与到响应者链条中.其实,对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以。所以,如果显示出来的东西需要跟用户进行交互的话,用UIView;如果不需要跟用户进行交互,用UIView或者CALayer都可以。当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级.
CALayer的使用说明:
通过UIView的layer属性可以拿到对应的根层,这个层不允许重新创建,但可以往层里面添加子层(调用CALayer的addSublayer)要具体使用CALayer,需要引入
获取当前图层或使用静态方法layer初始化CALayer后,可以设置以下属性:
bounds: 宽度和高度
position:位置(默认指中心点,具体由anchorPoint决定)
anchorPoint:锚点(x,y的范围都是0-1),决定了position的含义.默认值为(0.5,0.5)
backgroundColor: 背景颜色(CGColorRef类型)
borderColor:边框颜色(CGColorRef类型)
borderWidth:边框宽度
cornerRadius:圆角半径
contents: 内容(比如设置为图片CGImageRef)
transform:旋转、缩放、平移
contentsRect图层显示内容的大小和位置
doubleSided图层背面是否显示,默认为YES
注意:
1:虽然CALayer可以使用frame,但最好还是使用bounds和position。为层设置动画时,用bounds和position会方便一点.而且frame本身不支持动画效果,通常使用bounds和position代替.
2:隐式属性动画的本质是这些属性的变动默认隐含了CABasicAnimation动画实现.
3:CALayer中透明度使用opacity表示而不是alpha;中心点使用position表示而不是center。
4:anchorPoint属性是图层的锚点,范围在(0~1,0~1)表示在x、y轴的比例,这个点永远可以同position(中心点)重合,当图层中心点固定后,调整anchorPoint即可达到调整图层显示位置的作用(因为它永远和position重合).
#import "MainViewController.h"
#import
@implementation MainViewController
#define WIDTH 50
- (void)viewDidLoad
{
[super viewDidLoad];
[self myImageLayerDemo];//头像效果
//[self drawMyLayer];
//[self testAnchorPoint];
}
#pragma mark - UIImageView的layer演练
- (void)myImageLayerDemo
{
UIImage *image = [UIImage imageNamed:@"头像1.png"];
UIImageView *imageView = [[UIImageView alloc]initWithImage:image];
[imageView setFrame:CGRectMake(100,100,200,200)];
[self.view addSubview:imageView];
// 1. 圆角半径
//提示,在imageView中,图层不止一个,如果要实现圆角效果,需要设置一个遮罩属性
// masksToBounds属性可以让imageView中的所有子图层跟随imageView一起变化
imageView.layer.cornerRadius =50.0f;
[imageView.layer setMasksToBounds:YES];
// 2. 阴影
//提示,如果设置了masksToBounds属性,imageView的阴影效果无效.如果要实现阴影效果.解决办法:可以在底层附加一个UIView实现阴影效果.也可以通过Quartz 2D进行分别绘制.
[imageView.layer setShadowColor:[UIColor redColor].CGColor];//注意:UIKit框架只能应用在iOS而不能用于Mac,但是Quartz 2D是可以跨平台的,因此在使用颜色时,不能直接使用UIColor而需要将颜色转成CGColor.
[imageView.layer setShadowOffset:CGSizeMake(10.0,10.0)];
[imageView.layer setShadowOpacity:1.0];
// 3. 边框
[imageView.layer setBorderColor:[UIColor blueColor].CGColor];
[imageView.layer setBorderWidth:3.0f];
// 4. 形变属性,在CALayer中的形变属性是3D的,不再是2D的
//提示,形变参数使用set方法时,只能应用一种形变
// 1> 平移属性(向上移动100个点)
//[imageView.layer setTransform:CATransform3DMakeTranslation(0, -100, 0)];
// 2> 缩放属性
//[imageView.layer setTransform:CATransform3DMakeScale(0.5, 1.0, 1.0)];
// 3> 旋转属性
//提示:通常在旋转时指定z轴即可,要延哪个轴旋转,指定一个数值1.0即可
//图像本身没有厚度,如果按照x或y旋转90度,图像是不可见的。
//[imageView.layer setTransform:CATransform3DMakeRotation(M_PI_2, 0, 0, 1.0)];
// 5.利用keyPath设置形变,可以组合使用,但是记住不要写错了.
// 提示,在文档中输入transform3D可以找到对应的transform keyPath.可以传递哪些key path,在官方文档搜索 "CATransform3D key paths"
// 1)平移 -100及向上移动100个点.
[imageView.layer setValue:@-100 forKeyPath:@"transform.translation.y"];
// 2) 缩放 0.5及为原来大小的一半
[imageView.layer setValue:@0.5 forKeyPath:@"transform.scale"];
// 3) 旋转
[imageView.layer setValue:@M_PI_2 forKeyPath:@"transform.rotation.z"];
}
效果图如下:
#pragma mark 隐形动画的小例子 (每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)。所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画.) 程序初始化阶段我们定义一个正方形,但是圆角路径调整为正方形边长的一般,使其看起来是一个圆形,在点击屏幕的时候修改图层的属性形成动画效果(注意在程序中没有直接修改UIView的layer属性,因为根图层无法形成动画效果)
-(void)drawMyLayer{
CGSize size=[UIScreen mainScreen].bounds.size;
//获得根图层
CALayer *layer=[[CALayer alloc]init];
//设置背景颜色
layer.backgroundColor=[UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;
//设置中心点
layer.position=CGPointMake(size.width/2, size.height/2);
//设置大小
layer.bounds=CGRectMake(0,0,WIDTH,WIDTH);
//设置圆角,当圆角半径等于矩形的一半时看起来就是一个圆形
layer.cornerRadius=WIDTH/2;
//设置阴影
layer.shadowColor=[UIColor grayColor].CGColor;
layer.shadowOffset=CGSizeMake(2,2);
layer.shadowOpacity=.9;
[self.view.layer addSublayer:layer];
}
//点击放大,缩小
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch=[touches anyObject];
CALayer *layer=self.view.layer.sublayers[0];
CGFloat width=layer.bounds.size.width;
if (width==WIDTH) {
width=WIDTH*4;
}else{
width=WIDTH;
}
layer.bounds=CGRectMake(0,0, width, width);
layer.position=[touch locationInView:self.view];
layer.cornerRadius=width/2;
}
最开始运行得到的界面效果
点击界面之后,视图会以动画方式迅速移动到点击的位置并且变大
#pragma mark 瞄点的使用 如图所示:
anchorPoint
它的取值为0~1
红色图层的anchorPoint为(0,0)
红色图层的anchorPoint为(0.5,0.5)
红色图层的anchorPoint为(1,1)
红色图层的anchorPoint为(0.5,0)
position和anchorPoint
添加一个红色图层到绿色图层上,红色图层显示到什么位置,由position属性决定
假设红色图层的position是(100,100)
到底把红色图层的哪个点移动到(100,100)的坐标位置,锚点。
红色图层的锚点是(0,0)
红色图层的锚点是(0.5,0.5)
红色图层的锚点是(1,1)
红色图层的锚点是(0.5,0)
-(void)testAnchorPoint{
CALayer *myLayer=[CALayer layer];
//设置了myLayer的position为(100, 100),又因为anchorPoint默认是(0.5, 0.5),所以最后的效果是:myLayer的中点会在父层的(100, 100)位置
myLayer.bounds=CGRectMake(0,0,100,100);
// 设置层的位置
myLayer.position=CGPointMake(100,100);
myLayer.backgroundColor=[UIColor redColor].CGColor;
//情形1默认瞄点为(0.5, 0.5)
//情形2默认瞄点为(0, 0).
//myLayer.anchorPoint=CGPointMake(0,0);
//情形3默认瞄点为(1, 0).
//myLayer.anchorPoint=CGPointMake(1,0);
//情形4默认瞄点为(1, 1).
//myLayer.anchorPoint=CGPointMake(1,1);
// 添加myLayer到控制器的view的layer中
[self.view.layer addSublayer:myLayer];
}
@end
情形1默认瞄点为(0.5, 0.5)
情形2默认瞄点为(0, 0).
情形3默认瞄点为(1, 0).
情形4默认瞄点为(1, 1)