CALayer(二)

2018-08-10  本文已影响18人  莪的世界木有如果

这篇在介绍CALayer的使用基础上,会介绍CALayer的一些需要注意的属性设置。
github工程地址本篇内容主要在Layer/CALayer/UIView_CALayer里面

1、CALayer属性position和anchorPoint的关系

比如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

直接上代码:
先定义一个属性

/*随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;
}

实现结果

CALayer动画.gif

3、创建一个显示图片的layer

定义属性

/*显示图片的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

注意注意注意

_imageLayer.contents = (__bridge id)[UIImage imageNamed:@"banner"].CGImage;
_imageLayer.delegate = self;

因为self是UIView实例,所以这么写会导致崩溃;
那这个代理对象要怎么设置呢?其实这个和其他代理差不多,这里再controller里面设置

_layer.imageLayer.delegate = self;

这里的self是UIViewController实例,这样设置的话,就没有问题了;


这篇主要说的是CALayer的position和anchorPoint的关系;下篇会说CAlayer的子类CAShaperLayer

上一篇下一篇

猜你喜欢

热点阅读