美文网首页固予
CALayer、UIBezierPath、CGContextRe

CALayer、UIBezierPath、CGContextRe

作者: 慕言的世界 | 来源:发表于2016-11-22 16:48 被阅读239次

    Bezier、Layer、View三者之间的关系就好像是画笔、画布、画框的关系。
    Bezier:设置画笔的宽度、颜色、开始点、结束点等信息。
    Layer:所画的图形都是在layer上画出来(不响应点击事件)。
    View:展示画布,本身不具备画图的能力(响应点击时间)。
    (只是简单的类比帮助记忆,不准确。靠自己理解)

    Layer的使用

    Layer我们最常用的就是 View.layer.<#name#>来设置某些视图控件的圆角、阴影等。下面我们了解别的用法:

    3485760A-C65C-4D5E-963E-B2664D23BD56.png

    我们可以直接在紫色的视图上直接加一个红色的图层

        UIImageView *maskView = [[UIImageView alloc]initWithFrame:CGRectMake(50, 50, 200, 200)];
        maskView.backgroundColor = [UIColor purpleColor];
        [self.view addSubview:maskView];
    
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(50, 50, 100, 100);
        layer.backgroundColor = [UIColor redColor].CGColor;
        layer.cornerRadius = 6;
        [maskView.layer  addSublayer:layer];
    
    74DE0202-6AE7-43DB-AA96-9F9DC539EB11.png
      //给刚添加的红色图层添加内容
        layer.contents = (id)[UIImage imageNamed:@"<UIBarButtonSystemItem> add"].CGImage;
      //填充内容的contentMode
        layer.contentsGravity = kCAGravityResizeAspect;
        layer.opacity = 0.5;//透明度
    
    B2F69466-98DB-4D1A-BF86-65170E37B56E.png
    //注意:取值范围是0~1
        layer.contentsRect = CGRectMake(0, 0, 1, 0.5);//: 表示显示上半部分
    //注意:取值范围是0~1
    layer.anchorPoint = CGPointMake(0, 0);//anchorPoint是图层的中心点 默认(0.5,0.5) ,设置为多少那么中心点就在那里
    

    Layer 的mask蒙层

    这里说明一下mask的属性,mask的属性很简单,例如:view上加了一层imageView,如果imageView.layer.mask = layerA,那么layerA上不透明的部分将会被绘制成透明,透明的部分将会把imageView.layer绘制成透明的图层显示父视图的。


    这张图是借用别人的,不过这很形象的说明了mask的应用场景。

    256FBA35-9552-4D63-8EEF-FBBC98FAB3A6.png

    这个是我实现的结果 底下是一个满屏的图片 然后给layer的内容是这么一个十字架的图片 俩个合成现在的图片

        UIImageView *maskView = [[UIImageView alloc]initWithFrame:self.view.bounds];
        maskView.image = [UIImage imageNamed:@"白胡子.jpg"];
        [self.view addSubview:maskView];
        
        
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(50, 50, 100, 100);
    //    layer.backgroundColor = [UIColor redColor].CGColor; 
        layer.cornerRadius = 6;
        //add image
        layer.contents = (id)[UIImage imageNamed:@"<UIBarButtonSystemItem> add"].CGImage;
        //注意:取值范围是0~1
        layer.contentsRect = CGRectMake(0, 0, 1, 1);//: 表示显示全部
        layer.opacity = 0.5;
        layer.edgeAntialiasingMask = kCALayerBottomEdge;
        maskView.layer.mask =layer;
    

    CAShapeLayer 、 CAGradientLayer 是 CALayer的子类

    CAShapeLayer 基本用法一般与贝塞尔配合使用

    path// 
    fillColor//填充图形内部颜色
    strokeColor//填充线条的颜色
    strokeStart//开始点
    strokeEnd//结束点
    lineWidth//写的宽度
    miterLimit// 斜接长度指的是在两条线交汇处内角和外角之间的距离
    lineCap//线条结尾的样子 把线宽设置的大些才能明晰看到
    lineJoin//线条之间的结合点的样子 把线宽设置的大些才能明晰看到
    fillRule//判断内部外部 见详解 (http://blog.csdn.net/cuixiping/article/details/7848369)
    lineDashPhase//线型模板的起始位置
    lineDashPattern//线型模板  这是一个NSNumber的数组,索引从1开始记,奇数位数值表示实线长度,偶数位数值表示空白长度
    
    2606B1A0-185D-4BF9-AD1F-4A9680E7B34C.png
        CAShapeLayer *ShapeLayer = [CAShapeLayer layer];
        UIBezierPath *linePath = [UIBezierPath bezierPath];
        [linePath moveToPoint:CGPointMake(10, 200)];
        [linePath addLineToPoint: CGPointMake(200, 300)];
        [linePath addLineToPoint: CGPointMake(300, 10)];
        [linePath addLineToPoint: CGPointMake(10, 200)];
        linePath.lineCapStyle =kCGLineCapRound;
    //    [linePath addLineToPoint: CGPointMake(200, 300)];
        ShapeLayer.path = linePath.CGPath;
        ShapeLayer.lineWidth = 10.f;
        ShapeLayer.fillColor = [UIColor redColor].CGColor;
    //    ShapeLayer.opacity = 0.5f;
        //画线的开始和结束的地方0-1
    //    ShapeLayer.strokeStart = 0.7;
    //    ShapeLayer.strokeEnd = 0.8;
        ShapeLayer.strokeColor = [UIColor cyanColor].CGColor;
    //    maskView.layer.mask = ShapeLayer;
        ShapeLayer.lineJoin =kCALineJoinRound;
        ShapeLayer.lineCap = kCALineCapRound;
    //    ShapeLayer.fillRule = kCAFillRuleEvenOdd;
        ShapeLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:20], [NSNumber numberWithInt:20], [NSNumber numberWithInt:40], [NSNumber numberWithInt:40], nil];
        ShapeLayer.lineDashPhase = 0;
        
        [maskView.layer addSublayer:ShapeLayer];
    

    CAGradientLayer 的基本用法

    利用mask的特性做渐变的字体

        UILabel *textLabel  = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 20)];
        textLabel.text = @"我爱你Objct-C";
    //    textLabel.textColor = [UIColor redColor];
    //    textLabel.backgroundColor = [UIColor redColor];
        [self.view addSubview:textLabel];
        
        CAGradientLayer *gradientLayer = [CAGradientLayer layer];
        gradientLayer.frame = textLabel.frame;
        UIColor *beforeColor = [UIColor blueColor];
        UIColor *afterColor = [UIColor redColor];
        // 设置渐变层的颜色
        gradientLayer.colors = @[(id)beforeColor.CGColor,(id)afterColor.CGColor];
        [self.view.layer addSublayer:gradientLayer];//
        textLabel.layer.frame = gradientLayer.bounds;
        gradientLayer.mask = textLabel.layer;//maskview不能作为sub和super  所以不影响背景色
    
    01905598-CC22-48FE-A670-5AF1008CEEF8.png

    UIBezierPath 的基本用法

    此类是Core Graphics框架关于path的一个封装。使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。UIBezierPath对象是CGPathRef数据类型的封装。

    1.   + (instancetype)bezierPath;//创建并返回一个新的UIBezierPath对象(空的路径)
    2.   + (instancetype)bezierPathWithRect:(CGRect)rect;//创建并返回一个新的UIBezierPath对象,使用矩形路径初始化
    3.   + (instancetype)bezierPathWithOvalInRect:(CGRect)rect;//创建并返回一个新的椭圆路径的UIBezierPath对象:
    4.   + (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; //创建并返回一个新的圆角矩形路径的UIBezierPath对象:
    5.   + (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;//参数corners指定了想要需要成为圆角的角。可选值为:UIRectCorner 枚举
    6. 
     /**
     *  以某个中心点画弧线
     *  @param center     指定了圆弧所在正圆的圆心点坐标
     *  @param radius     指定了圆弧所在正圆的半径
     *  @param startAngle 指定了起始弧度位置  注意: 起始与结束这里是弧度 
     *  @param endAngle   指定了结束弧度位置  
     *  @param clockwise  指定了绘制方向,以时钟方向为判断基准   
     */
    + (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
    7.
      /**
     *  根据CGPath创建并返回一个新的UIBezierPath对象
     *  @param CGPath CGPathRef
     */
    + (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;
    8.  
    /**
     *  设置第一个起始点到接收器
     *  @param point 起点坐标
     */
    - (void)moveToPoint:(CGPoint)point;
    9.
    /**
     *  附加一条直线到接收器的路径
     *  @param point 要到达的坐标
     */
    - (void)addLineToPoint:(CGPoint)point;
    10.
    /**
     *  闭合线 使用这个方法起始点与终点将相连
     */
    - (void)closePath;
    11.
    /**
     *  移除所有坐标点
     */
    - (void)removeAllPoints;
    12.
    - (void)fill;// 填充颜色
    
    - (void)stroke;// 利用当前绘图属性沿着接收器的路径绘制
    13.
    /**
     *  该方法就是画三次贝塞尔曲线的关键方法,以三个点画一段曲线,一般和moveToPoint:配合使用。其实端点为moveToPoint:设置,终止端点位为endPoint;。控制点1的坐标controlPoint1,这个参数可以调整。控制点2的坐标是controlPoint2。
     *
     *  @param endPoint      终点坐标
     *  @param controlPoint1 控制点1
     *  @param controlPoint2 控制点2  
     */
    - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
    14.
    /**
     *  画二次贝塞尔曲线,是通过调用此方法来实现的。一般和moveToPoint:配合使用。endPoint终端点,controlPoint控制点,对于二次贝塞尔曲线,只有一个控制点
     *  @param endPoint     终点坐标
     *  @param controlPoint 控制点  
     */
    - (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
    

    这里我就放俩张网络的图片来帮助大家理解三次、二次贝塞尔曲线
    三次贝塞尔曲线


    二次贝塞尔曲线

    图片均来自网络

    CGContextRef

    此类是Core Graphics框架中的一员。Core Graphics提供了以下几个Graphics Context类型

    Bitmap Graphics Context
    PDF Graphics Context
    Window Graphics Context
    Layer Graphics Context
    Printer Graphics Context
    

    Graphics Context是图形上下文,是一个CGContextRef类型的数据;可以帮你把你要显示的图形显示到你指定的目标文件上。

    在drawRect:方法中取得上下文后,就可以绘制东西到view上
    View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去View之所以能显示东西,完全是因为它内部的layer

    CGContextRef的一些用法UIBezierPath已经封装好这里也不说了。如果大家有兴趣的可以看 iOS 2D绘图详解CGContextRef 基本认识点

    相关文章

      网友评论

      • My少了不少:我问一下讲那个CAShapeLayer的时候,画虚线,CGFloat hash[]={20,20,40,40};
        [path setLineDash:hash count:4 phase:0.0]; 直接用贝塞尔德方法不是更简单?为什么要写一个UIBezierPath 然后再写一个CAShapeLayer?这两个有什么区别?
      • jianshu小赵:不得了了
      • Henry725:View 负责交互,Layer 负责展示,各司其职,相同点是都有树状结构
        Henry725:@慕言的世界 我的理解是:View 相当于手机屏幕,可以触摸交互,Layer 相当于屏幕下面展示部分(类似投影仪的幕布)。。。。还有一点,UIBezierPath是UIKit的。。。有时间我也写几篇日志,可以相互交流下
        慕言的世界:@HonglingHe自己留着看的0.0。view 相当于画框,我想表达的就是画框展示画布。说的有问题了。
      • Henry725:感谢 LZ 分享,总结的不错 :+1:

      本文标题:CALayer、UIBezierPath、CGContextRe

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