CALayer 基础

<pre name="code" class="html">自定义图层  和  顺序  
- (void)viewDidLoad {
    
    [super viewDidLoad];

    MyView *muView = [[MyView alloc] initWithFrame:self.view.bounds];
    
    muView.backgroundColor = [UIColor redColor];
    //    muView.layer.delegate = muView;
    //    [muView setNeedsDisplay];
    [self.view addSubview:muView];
    //    [self diyLayer2];
    //
    //    // 视图图层的代理 是 视图本身  不能修改代理
    //    self.view.layer.delegate = self.view;
    
    // 0. 无论采取哪种方式,必须调用CALayer的setNeedDisplay才能正常显示图层
    
    // 1. 当UIView需要显示时,它内部的layer层会准备好一个CGContextRef图形上下文
    
    // 2. 调用delegate(UIView)的drawLayer:inContext方法,并且传入一个已经准备好的CGContextRef对象,
    //    而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法
    
    // 3. 平常在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入CGContextRef中,然后被拷贝至屏幕
    
    // 1. layer 会准备一个layer Graphics context 图形上下文
    // 2. 调用layer的代理方法画东西
    // 3. drawlayer:incontext会调用drawrect方法 drawrect会获取layer的图形上下文
    
}


- (void)diyLayer2 { // 代理画
    
    CALayer *layer = [CALayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.backgroundColor = [UIColor blueColor].CGColor;
    [layer setAnchorPoint:CGPointZero];
    // 设置代理
    
    layer.position = CGPointMake(30, 40);
    layer.delegate = self;
    [layer setNeedsDisplay];
    [self.view.layer addSublayer:layer];
    
}

#pragma mark - 图层 - 代理方法
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    
    CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
    CGContextAddRect(ctx, CGRectMake(0, 0, 30, 30));
    CGContextFillPath(ctx);
    
}

- (void)diyLayer {  // 自己画
    
    MyLayer *layer = [MyLayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.backgroundColor = [UIColor blueColor].CGColor;
    [layer setAnchorPoint:CGPointZero];
    [layer setNeedsDisplay];
    [self.view.layer addSublayer:layer];
}
#pragma mark - UIImageView的layer
- (void)myImageVieLayer {
    
    UIImage *image = [UIImage imageNamed:@"icon.jpg"];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    [imageView setFrame:CGRectMake(50, 50, 200, 200)];
    [self.view addSubview:imageView];
    
    // 1. 圆角半径
    // 提示:在imageView中,图层不只有一个,如果想要实现圆角效果,需要设置一个跟随属性
    // masksToBounds属性可以让imageView中的所有子图层跟随imageView一起变化
    imageView.layer.cornerRadius = 100.0f;
    // 跟随属性
    [imageView.layer setMasksToBounds:YES];
    
    // 2. 阴影
    // 提示:如果设置了makesToBounds属性,imageView的阴影效果无效
    [imageView.layer setShadowColor:[UIColor redColor].CGColor];
    [imageView.layer setShadowOffset:CGSizeMake(10, 10)];
    [imageView.layer setShadowOpacity:1.0f];
    
    // 3. 边框
    [imageView.layer setBorderColor:[UIColor blueColor].CGColor];
    [imageView.layer setBorderWidth:3.0f];
    
    // 4. 形变属性,在CALayer的属性是3D的,不再是2D的
    // 提示: 形变参数使用set方法时,只能应用一种形变(后面覆盖前面的。)
    // 1> 平移属性
    [imageView.layer setTransform:CATransform3DMakeTranslation(0, -100, 0)];// 向上移动100个点
    // 2> 缩放属性
    [imageView.layer setTransform:CATransform3DMakeScale(0.5, 1.0, 1.0)];
    // 3> 旋转属性
    // 要延哪个轴旋转,指定一个数值1.0即可,图像本身没有厚度,如果按照x或者y旋转90度,图像是不可见的。
    [imageView.layer setTransform:CATransform3DMakeRotation(M_PI/3, 1, 0, 0)];
    
    // 5. 利用keyPath设置形变属性  这几个属性可以组合用 和  4直接设置形变属性  不相同
    // 1> 平移属性
    [imageView.layer setValue:@-100 forKey:@"transform.translation.y"];
    // 2> 缩放属性
    [imageView.layer setValue:@0.5 forKey:@"transform.scale"];
    // 3> 旋转属性
    [imageView.layer setValue:@(M_PI_2) forKey:@"transform.rotation.z"];
}


#pragma mark - ‘自定义view的layer’
- (void)myViewLayer {
    
    // 在实现核心动画时,本质上是将CALayer中的内容转化为位图,从而便于图形图形的操纵
    // 每个UIView内部都有一个Layer属性
    
    self.view.backgroundColor = [UIColor lightGrayColor];
    
    // 1. 自定义UIView的图层属性
    UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
    myView.backgroundColor = [UIColor redColor];
    [self.view addSubview:myView];
    
    // 1) 圆角半径
    myView.layer.cornerRadius = 10.0f;
    
    // 2) 阴影
    // 因为CoreAnimation是跨平台的,基于QuartzCore框架,在CoreAnimation中不能使用任何跟UI有关的方法,是因为UIKit框架仅能适用于iOS平台
    // 要设置阴影除了颜色之外,还需要指定‘偏移量’和‘透明度’
    
    //      1>阴影颜色
    [myView.layer setShadowColor:[UIColor greenColor].CGColor];
    
    //      2>阴影偏移量  左 下
    [myView.layer setShadowOffset:CGSizeMake(10, 10)];
    
    //      3> 阴影透明度
    [myView.layer setShadowOpacity:1.0f];
    
    // 3) 边框
    [myView.layer setBorderWidth:3.0f];
    [myView.layer setBorderColor:[UIColor blueColor].CGColor];
}


 
创建 自定义图层  - 锚点的使用
    
    // 把内容画到自己的层上,当试视图在层上完成绘图后,系统会将图层拷贝到屏幕
    // 每个视图都有一个层,而每个图层又有很多层
    // layer的设计目的是提供视图的基本可视内容
    
    // 1. 自定义图层
    CALayer *myLayer = [CALayer layer];
    
    // 将自定义图层添加到视图的根图层之上
    [self.view.layer addSublayer:myLayer];
    self.myLayer = myLayer;
    
    // 2. 设置属性
    // 1> 设置边框
    [myLayer setBounds:CGRectMake(10, 10, 200, 200)];
    // 2> 设置背景颜色
    [myLayer setBackgroundColor:[UIColor redColor].CGColor];
    // 3> 设置中心点 (默认是0,0,对应着UIView的center) position相对于父图层的位置
    [myLayer setPosition:CGPointMake(10, 10)];
    // 4> 设置内容
    UIImage *image = [UIImage imageNamed:@"21.jpg"];
    [myLayer setContents:(id)image.CGImage];
    // 5> 锚点 它传说中也叫做定位点 (x,y的范围都是0-1) 决定了position的含义
    // 默认值 (0.5,0.5)
    // 作用:主要控制图层的位置 以及旋转的轴
    
    //~~~~ 通过比例,锚点不需要知道图层具体的大小啊,让锚点去找position吧~~~
    [myLayer setAnchorPoint:CGPointMake(1, 1)];
    //
    // [myLayer setTransform:CATransform3DMakeRotation(M_PI, 0, 0, 1)];
    

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    
    if (self.myLayer.anchorPoint.x == 0) {
        
        self.myLayer.anchorPoint = CGPointMake(1, 1);
    } else {
        
        self.myLayer.anchorPoint = CGPointMake(0, 0);
    }
}

隐式动画的属性 和 使用
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1. 实例化自定义图层
    CALayer *myLayer = [CALayer layer];
    // 这是bounds
    [myLayer setBounds:CGRectMake(0, 0, 100, 100)];
    // 这是背景颜色
    [myLayer setBackgroundColor:[UIColor redColor].CGColor];
    // 这是中心位置
    [myLayer setPosition:CGPointMake(50, 50)];
    
    [self.view.layer addSublayer:myLayer];
    self.myLayer = myLayer;
    self.myLayer.hidden = YES;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    
    self.myLayer.hidden = NO;
    UITouch *touch = touches.anyObject;
    CGPoint location = [touch locationInView:self.view];
    
    //    // 关闭动画  默认0.25秒
    //    [CATransaction begin];
    //    [CATransaction setDisableActions:YES];
    // 位置
    [self.myLayer setPosition:location];
    // 颜色
    CGFloat r = arc4random_uniform(256) / 255.0;
    CGFloat g = arc4random_uniform(256) / 255.0;
    CGFloat b = arc4random_uniform(256) / 255.0;
    UIColor *color = [UIColor colorWithRed:r green:g blue:b alpha:1.0f];
    // 随机颜色
    self.myLayer.backgroundColor = color.CGColor;
    
    // 随机透明度
    CGFloat alpha = (arc4random_uniform(5)+1.0)/10.0 + 0.5;
//    Opacity 不透明
    [self.myLayer setOpacity:alpha];
    
    // 尺寸
    NSInteger size  = arc4random_uniform(50) + 51;
    [self.myLayer setBounds:CGRectMake(20,20, size, size)];
    
    // 圆角
    NSInteger radius = arc4random_uniform(50);
    [self.myLayer setCornerRadius:radius];
    
    // 旋转角度
    CGFloat angle = arc4random_uniform(180) / 180.0*M_PI;
    [self.myLayer setTransform:CATransform3DMakeRotation(angle, 0, 0, 1)];
    
    // 内容
    //    self.myLayer setContents:<#(id)#>
    
    //    [CATransaction commit];
    
}



CALayer  图层通过代理
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1. 实例化子图层
    CALayer *myLayer = [CALayer layer];
    
    [myLayer setBounds:CGRectMake(0, 0, 200, 200)];
    [myLayer setBackgroundColor:[UIColor redColor].CGColor];
    [myLayer setCornerRadius:2.0f];
    [myLayer setPosition:CGPointMake(100, 100)];
    
    [self.view.layer addSublayer:myLayer];
    
    self.myLayer = myLayer;
    // 提示,如果要重绘CALayer,必须要调用setNeedDisplay
    
    // 不能够将视图设置为layer的代理
    [self.myLayer setDelegate:self];
    [self.myLayer setNeedsDisplay];
    NSLog(@"%@",self.myLayer);
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    
    NSLog(@"%@",layer);
    
    // 在core animation中不能使用UI的方法
    // 蓝色矩形矩形
//    [[UIColor blueColor] set];
    CGRect rect = CGRectMake(50, 50, 100, 100);
    CGContextSetRGBFillColor(ctx, 0, 0, 1.0, 1.0);
    CGContextSetRGBStrokeColor(ctx, 0, 1, 0, 1);
    
    CGContextAddRect(ctx, rect);
    CGContextDrawPath(ctx, kCGPathEOFillStroke);
    
//    UIRectFill(rect);
    
    
}

自定义Layer
- (void)drawInContext:(CGContextRef)ctx {
    
    NSLog(@"drawInContect");
    // 绘图层Ellipse 圆形
    // 青色的圆
    CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));
    CGContextSetRGBFillColor(ctx, 0, 1.0, 1.0, 1.0);
    CGContextDrawPath(ctx, kCGPathFill);
//    CGContextFillPath(ctx);
    
    // 蓝色的圆
    CGContextAddEllipseInRect(ctx, CGRectMake(100, 100, 100, 100));
    CGContextSetRGBFillColor(ctx, 0, 0, 1.0, 1.0);
    CGContextDrawPath(ctx, kCGPathFill);
    
    // 绘制头像
    // 在绘图的时候可以利用上下文的形变来画图
    // 可以利用形变属性的缩放实现图片的反转 (1,-1)
    // 利用平移恢复位置(向下平移坐标系)
    CGContextScaleCTM(ctx, 1.0, -1.0);
    CGContextTranslateCTM(ctx, 0, -self.bounds.size.height);
    UIImage *image = [UIImage imageNamed:@"icon.jpg"];
    CGContextDrawImage(ctx, CGRectMake(50, 50, 100, 100), image.CGImage);
    
    
    
}

跟上一个衔接。
@interface MyView ()
@property (nonatomic,weak) MyLayer *myLayer;
@end

@implementation MyView


- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
        
        NSLog(@"init view");
        
        MyLayer *myLayer = [MyLayer layer];
        [self.layer addSublayer:myLayer];
        
        [myLayer setBackgroundColor:[UIColor redColor].CGColor];
        [myLayer setBounds:self.bounds];
        [myLayer setPosition:CGPointMake(100, 100)];
        
        self.myLayer = myLayer;
        
        [self.myLayer setNeedsDisplay];
        
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    
    NSLog(@"drawRect");
}

/** 会先调用这个方法,然后调用drawrect方法 */
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    
    [super drawLayer:layer inContext:ctx];
    NSLog(@"draw layer");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为下列代码实现可暂停效果: import UIKit class ViewController: UIViewController { private let radarAnimation = "radarAnimation" private var animationLayer: CALayer? private var animationGroup: CAAnimationGroup? private var opBtn: UIButton! override func viewDidLoad() { super.viewDidLoad() let first = makeRadarAnimation(showRect: CGRect(x: 120, y: 100, width: 100, height: 100), isRound: true) view.layer.addSublayer(first) opBtn = UIButton(frame: CGRect(x: 100, y: 450, width: 80, height: 80)) opBtn.backgroundColor = UIColor.red opBtn.clipsToBounds = true opBtn.setTitle("Hsu", for: .normal) opBtn.layer.cornerRadius = 10 view.addSubview(opBtn) let second = makeRadarAnimation(showRect: opBtn.frame, isRound: false) view.layer.insertSublayer(second, below: opBtn.layer) } @IBAction func startAction(_ sender: UIButton) { animationLayer?.add(animationGroup!, forKey: radarAnimation) } @IBAction func stopAction(_ sender: UIButton) { animationLayer?.removeAnimation(forKey: radarAnimation) } private func makeRadarAnimation(showRect: CGRect, isRound: Bool) -> CALayer { // 1. 一个动态波 let shapeLayer = CAShapeLayer() shapeLayer.frame = showRect // showRect 最大内切圆 if isRound { shapeLayer.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: showRect.width, height: showRect.height)).cgPath } else { // 矩形 shapeLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: showRect.width, height: showRect.height), cornerRadius: 10).cgPath } shapeLayer.fillColor = UIColor.orange.cgColor // 默认初始颜色透明度 shapeLayer.opacity = 0.0 animationLayer = shapeLayer // 2. 需要重复的动态波,即创建副本 let replicator = CAReplicatorLayer() replicator.frame = shapeLayer.bounds replicator.instanceCount = 4 replicator.instanceDelay = 1.0 replicator.addSublayer(shapeLayer) // 3. 创建动画组 let opacityAnimation = CABasicAnimation(keyPath: "opacity") opacityAnimation.fromValue = NSNumber(floatLiteral: 1.0) // 开始透明度 opacityAnimation.toValue = NSNumber(floatLiteral: 0) // 结束时透明底 let scaleAnimation = CABasicAnimation(keyPath: "transform") if isRound { scaleAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DScale(CATransform3DIdentity, 0, 0, 0)) // 缩放起始大小 } else { scaleAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0)) // 缩放起始大小 } scaleAnimation.toValue = NSValue.init(caTransform3D: CATransform3DScale(CATransform3DIdentity, 1.5, 1.5, 0)) // 缩放结束大小 let animationGroup = CAAnimationGroup() animationGroup.animations = [opacityAnimation, scaleAnimation] animationGroup.duration = 3.0 // 动画执行时间 animationGroup.repeatCount = HUGE // 最大重复 animationGroup.autoreverses = false self.animationGroup = animationGroup shapeLayer.add(animationGroup, forKey: radarAnimation) return replicator } }
最新发布
06-03

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值