这篇在介绍CALayer的使用基础上,会介绍CALayer的一些需要注意的属性设置。
github工程地址本篇内容主要在Layer/CALayer/UIView_CALayer
里面
1、CALayer属性position和anchorPoint的关系
- 1.position:用于设置CALayer的位置。修改这个属性会产生平移动画,这个position相当于UIView的center属性
- 2.anchorPoint:锚点指定了position在当前图层中的位置,坐标范围0~1。position点的值是相对于父图层的,而这个position到底位于当前图层的什么地方,是由锚点决定的。(默认在图层的中心,即锚点为(0.5,0.5) )
-3.position和anchorPoint这两个点一定是重合的,position确定后,anchorPoint的改变会改变layer的位置;
比如layer的bounds为(0,0,100,100)position为(50,50), anchorPoint为(0,0),这个时候position点基于父图层还是(50,50),但是在layer上是在layer左上角的(0,0)位置,这个时候layer的frame的origin为(50,50);如果anchorPoint为(0.5,0.5),此时layer的frame的origin为(0,0)。
下面验证上面的概述,先声明三个属性:CATextLayer是继承于CALayer的。
/*定义CALayer属性,position为(100,100) anchorPoint为默认值(0.5,0.5)*/
@property (nonatomic,strong) CATextLayer *myLayer;
/*position为(100,200),anchorPoint为(0,0)*/
@property (nonatomic,strong) CATextLayer *myLayer1;
/*position为(100,300),anchorPoint为(1,1)*/
@property (nonatomic,strong) CATextLayer *myLayer2;
再来看看实现部分:
/*懒加载*/
- (CATextLayer *)myLayer
{
if(!_myLayer){
_myLayer = [[CATextLayer alloc] init];
//设置大小
_myLayer.bounds = CGRectMake(0, 0, 100, 100);
//设置背景颜色
_myLayer.backgroundColor = [UIColor redColor].CGColor;
//设置position(center)
_myLayer.position = CGPointMake(100, 100);
//设置anchorPoint
_myLayer.anchorPoint = CGPointMake(0, 0);
//设置显示的文字,这里显示的anchorPoint的值
_myLayer.string = @"(0,0)";
//设置显示字体的大小
_myLayer.fontSize = 15.f;
//设置字体的颜色
_myLayer.foregroundColor = [UIColor blackColor].CGColor;
}
return _myLayer;
}
/*懒加载*/
- (CATextLayer *)myLayer1
{
if(!_myLayer1){
_myLayer1 = [[CATextLayer alloc] init];
_myLayer1.bounds = CGRectMake(0, 0, 100, 100);
_myLayer1.backgroundColor = [UIColor yellowColor].CGColor;
_myLayer1.position = CGPointMake(100, 100);
_myLayer1.anchorPoint = CGPointMake(0, 1);
_myLayer1.string = @"(0,1)";
_myLayer1.fontSize = 15.f;
_myLayer1.foregroundColor = [UIColor blackColor].CGColor;
}
return _myLayer1;
}
/*懒加载*/
- (CATextLayer *)myLayer2
{
if(!_myLayer2){
_myLayer2 = [[CATextLayer alloc] init];
_myLayer2.bounds = CGRectMake(0, 0, 100, 100);
_myLayer2.backgroundColor = [UIColor greenColor].CGColor;
_myLayer2.position = CGPointMake(100, 100);
_myLayer2.anchorPoint = CGPointMake(1, 0);
_myLayer2.string = @"(1,0)";
_myLayer2.fontSize = 15.f;
_myLayer2.foregroundColor = [UIColor blueColor].CGColor;
}
return _myLayer2;
}
上面别设置了三个大小一样,position设置一样,但是anchorPoint设置不一样,由于anchorPoint的值决定position在自己layer上的位置,所以三个layer虽然大小一样,position一样,但是由于anchorPoint不一样,使得layer在父视图上的位置不一样,如图:
image.png
2、这里再实现一个跟着点击屏幕的手指移动的layer
- 实现原理主要是改变position为当前手指点击的点
直接上代码:
先定义一个属性
/*随touch点移动的animationLayer*/
@property (nonatomic,strong) CALayer *animationLayer;
.m实现部分
/*动画layer*/
- (CALayer *)animationLayer
{
if(!_animationLayer){
_animationLayer = [CALayer layer];
// 设置背景颜色
_animationLayer.backgroundColor = [UIColor colorWithRed:0.1 green:0.2 blue:0.3 alpha:1].CGColor;
// 设置中心点
_animationLayer.position = CGPointMake(kWidth/2, kHeight/2);
// 设置大小
_animationLayer.bounds = CGRectMake(0, 0, 100, 100);
// 设置圆角,当圆角半径等于大小的一半时,则显示出来的是圆形
_animationLayer.cornerRadius = 50;
// 设置阴影
_animationLayer.shadowColor = [UIColor grayColor].CGColor;
// 设置阴影偏移量
_animationLayer.shadowOffset = CGSizeMake(3, 1);
// 设置阴影的透明度
_animationLayer.shadowOpacity = 0.9;
// 设置边框
// _animationLayer.borderColor = [UIColor whiteColor].CGColor;
// 设置边框大小
// _animationLayer.borderWidth = 1;
// 设置锚点
// _animationLayer.anchorPoint = CGPointZero;
}
return _animationLayer;
}
touch结束处理事件
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 获取手指的点击事件的touch
UITouch * touch = [touches anyObject];
// 获取当前layer的宽度
CGFloat width = self.animationLayer.bounds.size.width;
// 设置宽度
if (width == 100) {
width = 2 * 100;
}else{
width = 100;
}
self.animationLayer.bounds = CGRectMake(0, 0, width, width);
// 设置position
self.animationLayer.position = [touch locationInView:self];
// 设置圆角
self.animationLayer.cornerRadius = width/2;
}
实现结果
3、创建一个显示图片的layer
- 实现原理是利用Layer的contents来显示image的CGimageref内容
定义属性
/*显示图片的layer*/
@property (nonatomic,strong) CALayer *imageLayer;
实现代码*
/*显示图层的layer*/
- (CALayer *)imageLayer
{
if(!_imageLayer){
_imageLayer = [CALayer layer];
// 设置大小
_imageLayer.bounds = CGRectMake(0, 0, 100, 100);
// 设置position
_imageLayer.position = CGPointMake(200, 100);
// 设置背景颜色
_imageLayer.backgroundColor = [UIColor redColor].CGColor;
// 设置圆角
_imageLayer.cornerRadius = 100/2;
// 如果要正确显示出图片,就要设置masksToBounds = YES,剪切子图层
_imageLayer.masksToBounds = YES;
// 注意:阴影效果无法和masksToBounds同时使用,因为masksToBounds的目的就是剪切外边框,阴影刚好处于外边框
// 设置边框
_imageLayer.borderColor = [UIColor yellowColor].CGColor;
// 设置边框宽度
_imageLayer.borderWidth = 2;
[self.layer addSublayer:_imageLayer];
/**
* 给图层设置图片内容,可以使用 CALayerDelegate的
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
方法重绘,但是代理对象不能指定UIView的实例对象,如果指定的是UIView实例对象,
则会导致cash。可以在Controller里面指定代理,然后实现代理方法重绘;
要想代理方法实现,还必须调用 setNeedsDisplay 方法,否则代理方法不会调用
* 如果只是单单的显示图片,设置layer的contents的内容就可以了!
*/
_imageLayer.contents = (__bridge id)[UIImage imageNamed:@"banner"].CGImage;
}
return _imageLayer;
}
调用
/*CALayer*/
- (UIView_CALayer *)layer
{
if(!_layer){
_layer = [[UIView_CALayer alloc] initWithFrame:CGRectMake(0, 64, kWidth, kHeight)];
//CALayerDelegate的指定的代理对象不能是UIView的实例对象,否则会造成cash;
_layer.imageLayer.delegate = self;
[self.view addSubview:_layer];
// 如果不调用这个方法,则代理方法- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;不会调用
[_layer.imageLayer setNeedsDisplay];
}
return _layer;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
CGContextSaveGState(ctx);
// 图形上下文形变,解决图片倒立问题
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -100);
UIImage *img = [UIImage imageNamed:@"banner"];
// 注意这个位置是相对于图层而言而不是屏幕
//CGContextDrawImage(ctx, CGRectMake(0, 0, 100, 100), img.CGImage);
CGContextRestoreGState(ctx);
}
给图层设置图片内容,可以使用 CALayerDelegate的
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
方法重绘,但是代理对象不能指定UIView的实例对象,如果指定的是UIView实例对象,则会导致cash。可以在Controller里面指定代理,然后实现代理方法重绘;要想代理方法实现,还必须调用 setNeedsDisplay 方法,否则代理方法不会调用
实现结果
显示图片的CALayer注意注意注意
- 1.如果只是显示图片,那么可以直接设置layer的contents的内容就可以
_imageLayer.contents = (__bridge id)[UIImage imageNamed:@"banner"].CGImage;
- 2.如果要使用绘图的方式来显示图层,就需要设置代理,但是这个代理对象不能为UIView的实例对象,比如在UIView里面设置
_imageLayer.delegate = self;
因为self是UIView实例,所以这么写会导致崩溃;
那这个代理对象要怎么设置呢?其实这个和其他代理差不多,这里再controller里面设置
_layer.imageLayer.delegate = self;
这里的self是UIViewController实例,这样设置的话,就没有问题了;
这篇主要说的是CALayer的position和anchorPoint的关系;下篇会说CAlayer的子类CAShaperLayer
网友评论