美文网首页
CALayer(二)

CALayer(二)

作者: 莪的世界木有如果 | 来源:发表于2018-08-10 14:16 被阅读18次

    这篇在介绍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;
    }
    

    实现结果

    CALayer动画.gif

    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

    相关文章

      网友评论

          本文标题:CALayer(二)

          本文链接:https://www.haomeiwen.com/subject/ocrkbftx.html