CALayer相关

UIView能显示在屏幕上,全靠内部有一个Layer图层,在创建UIView的时候,同时会在内部创建一个图层CALayer,可以通过layer属性访问。当UIView需要显示到屏幕上,会调用drawRect方法绘图,并且将内容绘制在图层上,绘图完毕后,系统会将图层拷贝到屏幕上,完成UIView的显示

通过操作CALayer对象,很方便的调整UIView的一些外观属性

UIView对layer的一些操作

//设置阴影的大小
[self.subview.layer setShadowOpacity:5];
//设置阴影的颜色
[self.subview.layer setShadowColor:[UIColor blackColor].CGColor];
//设置阴影的偏移位置
[self.subview.layer setShadowOffset:CGSizeMake(5, 5)];
//设置阴影的模糊半径
[self.subview.layer setShadowRadius:10];

//设置边框颜色
[self.subview.layer setBorderColor:[UIColor whiteColor].CGColor];
//设置边框宽度
[self.subview.layer setBorderWidth:5];
//设置边框圆角半径
[self.subview.layer setCornerRadius:30];

以上设置也同样用于UIImageView,但是

[self.imageView.layer setCornerRadius:54];

虽然设置了圆角半径,却无法遮盖图像,图像多出的部分依然显示,这是因为图片实际上是存放在layer中的一个contents中,如果要图像能被遮盖注,就需要剪裁多出来的部分,使用:

[self.imageView.layer setMasksToBounds:YES];

这样layer超过border的部分就会被裁剪,不过这样图像设置的阴影也会超过边框,也被一并裁剪

自定义创建一个CALayer

CALayer *layer = [CALayer layer];
layer.bounds = CGRectMake(0,0,100,100);
layer.backgroundColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:layer];

position和anchorPoint

设置CALayer在父层的位置

@property CGPoint position;

anchorPoint以CALayer左上角(0,0)为原点,取值范围为0~1,默认值为(0.5,0.5),也就是相对于CALayer宽和高的一个比例值,这个点是和position重合的,也就是说,CALayer的position在哪里,CALayer就将自己的anchorPoint对准position来显示CALayer。anchorPoint也称为定位点、锚点

@property CGPoint anchorPoint;

层内容的可视区域

@property CGRect contentsRect;

内容的矩形区域(x,y,width,height)也是绑定到层的框架上的。contentRect是一个比例值,而不是屏幕上真实的像素点。默认的是0.0,0.0,1.0,1.0.当你改变x时,例如,在0和1之间你设定为0.25,那么内容的观察窗口就展示在400像素中的100像素的位置(400 x 0.25),也就是一个层原始宽度的25%。如果你设定了width属性为0.25,那么观察窗口的宽度就是100,也就是一个层原始宽度的25%。

关于CALayer的一些疑惑

CALayer定义在QuartzCore框架中
CGImageRef,CGColorRef定义在CoreGraphics框架中
UIColor,UIImage是定义在UIKit框架中

QuartzCore和CoreGraphics框架是可以跨平台使用的,在iOS和Mac上都能使用,但是UIKit只能用于iOS

为了保证可移植性,QuartzCore不能使用UIImage,UIColor,只能使用CGImageRef,CGColorRef

和UIView相比CALayer是没有事件处理的功能,比如不能通过触摸交互。如果只是做显示对象,两种都可选用,相比之下,CALayer的性能高些,因为没有事件处理

隐式动画

每一个UIView中都有默认关联的一个layer,称为rootLayer,手动创建的layer为非rootlayer,当非rootlayer的属性进行修改时,默认会自动产生动画效果,这些属性称为Animatable Properties(隐式动画),rootLayer是没有隐式动画的,如果希望屏蔽隐式动画,需要设置:

[CATransaction setDisableActions:YES];

需要设置隐式动画的速度:

[CATransaction setAnimationDuration:5];

设置隐式动画的开始和结束

[CATransaction begin];//开始
[CATransaction commit];//结束

CAGradientLayer渐变层

创建一个渐变层

//创建一个渐变图层
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
//设置图层的frame
gradientLayer.frame = self.view.bounds;
//设置图层的颜色数组,有多少种颜色参与渐变就写多少个CGColor
gradientLayer.colors = @[(id)[UIColor redColor].CGColor,(id)[UIColor blueColor].CGColor,(id)[UIColor greenColor].CGColor];
//映射locations中第一个位置,用单位向量表示,比如(0,0)表示从左上角开始变化。默认值是(0.5,0.0)。
gradientLayer.startPoint = CGPointMake(0, 1);
//映射locations中最后一个位置,用单位向量表示,比如(1,1)表示到右下角变化结束。默认值是(0.5,1.0)。
gradientLayer.endPoint = CGPointMake(0, 0);
//渐变颜色的区间分布,locations的数组长度和color一致,默认是nil,会平均分布。
//注意这几个数字在0到1之间单调递增
gradientLayer.locations = @[@0.3,@0.7];
//设置渐变层的透明度
gradientLayer.opacity = 0.5;
//添加渐变层到view中
[self.view.layer addSublayer:gradientLayer];

CAReplicatorLayer复制层

//创建一个复制层
CAReplicatorLayer *repeatLayer = [CAReplicatorLayer layer];
//设置复制层的背景
repeatLayer.backgroundColor = [UIColor blueColor].CGColor;
//设置复制层frame
repeatLayer.frame = self.containerView.bounds;
//每一份复制对象的动画执行延时间隔
repeatLayer.instanceDelay = 1;
//复制对象的个数
repeatLayer.instanceCount = 3;
//复制对象的变形,比如每个对象相对位移100
repeatLayer.instanceTransform = CATransform3DMakeTranslation(100, 0, 0);
//添加复制层倒UIView
[self.containerView.layer addSublayer:repeatLayer];

//创建一个要复制的层,并添加核心动画
CALayer *layer = [CALayer layer];
layer.backgroundColor = [UIColor greenColor].CGColor;
layer.bounds = CGRectMake(0, 0, 30, 200);
layer.anchorPoint = CGPointMake(0, 1);
layer.position = CGPointMake(0,self.containerView.bounds.size.height);

CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform.scale.y";
animation.toValue = @0;
animation.autoreverses = YES;
animation.removedOnCompletion = NO;
animation.repeatCount = MAXFLOAT;
animation.fillMode = kCAFillModeForwards;
animation.duration = 1;
[layer addAnimation:animation forKey:nil];

//创建一个要复制的层,并添加核心动画
CALayer *layer2 = [CALayer layer];
layer2.backgroundColor = [UIColor redColor].CGColor;
layer2.bounds = CGRectMake(0, 0, 30, 200);
layer2.anchorPoint = CGPointMake(0, 1);
layer2.position = CGPointMake(layer.bounds.size.width + 20, self.containerView.bounds.size.height);
layer2.transform = CATransform3DMakeScale(1, 0, 0);

CABasicAnimation *animation2 = [CABasicAnimation animation];
animation2.keyPath = @"transform.scale.y";
animation2.toValue = @1;
animation2.autoreverses = YES;
animation2.removedOnCompletion = NO;
animation2.repeatCount = MAXFLOAT;
animation2.fillMode = kCAFillModeForwards;
animation2.duration = 1;
[layer2 addAnimation:animation2 forKey:nil];

//将上面创建的2个layer放到复制层中,这样,复制层就会把这2个layer复制3份
[repeatLayer addSublayer:layer];
[repeatLayer addSublayer:layer2];

CAShapeLayer 形状图层

普通CALayer在被初始化时是需要给一个frame值的,这个frame值一般都与给定view的bounds值一致,它本身是有形状的,而且是矩形.

CAShapeLayer在初始化时也需要给一个frame值,但是,它本身没有形状,它的形状来源于你给定的一个path,然后它去取CGPath值,它与CALayer有着很大的区别

CAShapeLayer有着几点很重要:

  1. 它依附于一个给定的path,必须给与path,而且,即使path不完整也会自动首尾相接

  2. strokeStart以及strokeEnd代表着在这个path中所占用的百分比

  3. CAShapeLayer动画仅仅限于沿着边缘的动画效果,它实现不了填充效果

以下给出如何使用CAShapeLayer

@property (nonatomic, strong) CAShapeLayer *shapeLayer;

- (void)viewDidLoad {
    [super viewDidLoad];

    //创建出CAShapeLayer
    self.shapeLayer = [CAShapeLayer layer];
    self.shapeLayer.frame = CGRectMake(0, 0, 200, 200);//设置shapeLayer的尺寸和位置
    self.shapeLayer.position = self.view.center;
    self.shapeLayer.fillColor = [UIColor clearColor].CGColor;//填充颜色为ClearColor

    //设置线条的宽度和颜色
    self.shapeLayer.lineWidth = 1.0f;
    self.shapeLayer.strokeColor = [UIColor redColor].CGColor;

    //创建出圆形贝塞尔曲线
    UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];

    //让贝塞尔曲线与CAShapeLayer产生联系
    self.shapeLayer.path = circlePath.CGPath;

    //添加并显示
    [self.view.layer addSublayer:self.shapeLayer];
}

results matching ""

    No results matching ""