美文网首页
CGContext-上下文(画布)的应用

CGContext-上下文(画布)的应用

作者: 将军走路 | 来源:发表于2017-08-23 16:09 被阅读0次

    在uiview的- (void)drawRect:(CGRect)rect方法之前会自动生成一个画布并放在栈顶。通过UIGraphicsGetCurrentContext()方法获取当前的画布。
    苹果原本文档如下:

    The current graphics context is nil
    by default. Prior to calling its drawRect:
    method, view objects push a valid context onto the stack, making it current. If you are not using a UIView
    object to do your drawing, however, you must push a valid context onto the stack manually using the UIGraphicsPushContextfunction.

    上下文的用处一般有三种,本文介绍第一种

    1. UIView调用drawRect:之前系统生成的,用于界面的绘制;
    2. UIGraphicsBeginImageContext(), 用于生成图片;
    3. UIGraphicsBeginPDFContextToFile和UIGraphicsBeginPDFContextToData,用于生成PDF;

    1、画布的坐标转换(Coordinate space transformations)

    当前变换矩阵CTM(current transformation matrix )用来改变坐标环境,实现画布的平移、缩放、旋转等操作。

    • 画布平移

    /* Translate the current graphics state's transformation matrix (the CTM) by
    `(tx, ty)'. */
    CG_EXTERN void CGContextTranslateCTM(CGContextRef cg_nullable c,
    CGFloat tx, CGFloat ty)
    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

    • 画布缩放

    /* Scale the current graphics state's transformation matrix (the CTM) by
    `(sx, sy)'. */
    CG_EXTERN void CGContextScaleCTM(CGContextRef cg_nullable c,
    CGFloat sx, CGFloat sy)
    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

    • 画布旋转

    /* Rotate the current graphics state's transformation matrix (the CTM) by
    `angle' radians. */
    CG_EXTERN void CGContextRotateCTM(CGContextRef cg_nullable c, CGFloat angle)
    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

    • 将变换矩阵合并到画布中
      之前有写过关于仿射矩阵变换的简书文章,此处就是放射变换方法的一处应用场景

    /* Concatenate the current graphics state's transformation matrix (the CTM)
    with the affine transform `transform'. */
    CG_EXTERN void CGContextConcatCTM(CGContextRef cg_nullable c,
    CGAffineTransform transform)
    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

    • 获取当前变换矩阵

    /* Return the current graphics state's transformation matrix. Returns
    CGAffineTransformIdentity in case of inavlid context. */
    CG_EXTERN CGAffineTransform CGContextGetCTM(CGContextRef cg_nullable c)
    CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

    实例

    将一个字符串画到UIView 上,偏移tx=10,ty=10,放大2倍,旋转45度。

    - (void)drawRect:(CGRect)rect {
        // Drawing code
        CGContextRef ct = UIGraphicsGetCurrentContext();
        // 放大 2 倍
        CGContextScaleCTM(ct, 2, 2);
        // 移动 10
        CGContextTranslateCTM(ct, 10, 10);
        // 旋转 绕45度
        CGContextRotateCTM(ct, M_PI_4);
        [@"将军走路" drawInRect:rect withAttributes:@{NSForegroundColorAttributeName:[UIColor blueColor],NSFontAttributeName:[UIFont systemFontOfSize:14],NSBackgroundColorAttributeName:[UIColor cyanColor]}];
        
    }
    

    最终效果如下:


    E8864BF2-347B-4A83-854E-EDC5064B11C7.png

    注意所有的操作都是针对画布坐标的变换,所以并不是中心旋转,而是坐标的变换。所以转换的顺序不一样,得到的结果也不一样。把代码调一下顺序,得到的结果如下:

        - (void)drawRect:(CGRect)rect {
        // Drawing code
        CGContextRef ct = UIGraphicsGetCurrentContext();
        // 旋转 绕45度
        CGContextRotateCTM(ct, M_PI_4);
        // 放大 2 倍
        CGContextScaleCTM(ct, 2, 2);
        // 移动 10
        CGContextTranslateCTM(ct, 10, 10);
        [@"将军走路" drawInRect:rect withAttributes:@{NSForegroundColorAttributeName:[UIColor blueColor],NSFontAttributeName:[UIFont systemFontOfSize:14],NSBackgroundColorAttributeName:[UIColor cyanColor]}];
    
    }
    
    017BEAC4-6418-4E90-9AC2-FD83CFECA0F4.png

    2、上下文的绘图方式(Path drawing functions)

    基本绘制方法

    void CGContextDrawPath(CGContextRef cg_nullable c,
    CGPathDrawingMode mode)

    typedef CF_ENUM (int32_t, CGPathDrawingMode) {
    kCGPathFill, //填充
    kCGPathEOFill,//奇偶填充
    kCGPathStroke,//划线
    kCGPathFillStroke,//填充并划线
    kCGPathEOFillStroke //奇偶填充并划线
    };

    苹果提供的一些方便的绘制方法
    • CGContextFillPath
    • CGContextEOFillPath
    • CGContextStrokePath
    • CGContextFillRect
    • CGContextFillRects
    • CGContextStrokeRect
    • CGContextStrokeRectWithWidth
    • CGContextClearRect
    • CGContextFillEllipseInRect
    • CGContextStrokeEllipseInRect
    • CGContextStrokeLineSegments

    3、上下文绘制属性设置方法(Drawing attribute functions)

    • void CGContextSetLineWidth(CGContextRef cg_nullable c, CGFloat width)

    • void CGContextSetLineCap(CGContextRef cg_nullable c, CGLineCap cap)

    • void CGContextSetLineJoin(CGContextRef cg_nullable c, CGLineJoin join)

    • void CGContextSetMiterLimit(CGContextRef cg_nullable c, CGFloat limit)

    • void CGContextSetLineDash(CGContextRef cg_nullable c, CGFloat phase,
      const CGFloat * __nullable lengths, size_t count)

    • void CGContextSetFlatness(CGContextRef cg_nullable c, CGFloat flatness)

    • void CGContextSetAlpha(CGContextRef cg_nullable c, CGFloat alpha)

    • void CGContextSetBlendMode(CGContextRef cg_nullable c, CGBlendMode mode)

    4、路径的构建(Path construction functions)

    路径的基本构建方法
    • void CGContextBeginPath(CGContextRef cg_nullable c)

    • void CGContextMoveToPoint(CGContextRef cg_nullable c,
      CGFloat x, CGFloat y)

    • void CGContextAddLineToPoint(CGContextRef cg_nullable c,
      CGFloat x, CGFloat y)

    • void CGContextAddCurveToPoint(CGContextRef cg_nullable c, CGFloat cp1x,
      CGFloat cp1y, CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y)

    • void CGContextAddQuadCurveToPoint(CGContextRef cg_nullable c,
      CGFloat cpx, CGFloat cpy, CGFloat x, CGFloat y)

    • void CGContextClosePath(CGContextRef cg_nullable c)

    在基本构建方法上,苹果有封装了一些方便的构建方法
    • void CGContextAddRect(CGContextRef cg_nullable c, CGRect rect)
    • void CGContextAddRects(CGContextRef cg_nullable c,
      const CGRect * __nullable rects, size_t count)
    • void CGContextAddLines(CGContextRef cg_nullable c,
      const CGPoint * __nullable points, size_t count)
    • void CGContextAddEllipseInRect(CGContextRef cg_nullable c, CGRect rect)
    • void CGContextAddArc(CGContextRef cg_nullable c, CGFloat x, CGFloat y,
      CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
    • void CGContextAddArcToPoint(CGContextRef cg_nullable c,
      CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius)
    • void CGContextAddPath(CGContextRef cg_nullable c,
      CGPathRef cg_nullable path)

    实例

    画虚线
    • 效果


      AA377882-6056-47A6-83C7-9A9BA7C6707C.png
    • 代码及注释

        //设置为虚线
    //    CGFloat lengths[] = {2,2};
    //    CGContextSetLineDash(ct, 0, lengths, 2);
        //默认线条的cap类型就是kCGLineCapButt,而且,虚线必须是这个类型
    //    CGContextSetLineCap(ct, kCGLineCapButt);
    //    CGContextSetLineCap(ct, kCGLineCapRound);
    //    CGContextSetLineCap(ct, kCGLineCapSquare);
    
        CGPoint points[] = {
            CGPointMake(10, 10),CGPointMake(50, 10),
            CGPointMake(50, 10),CGPointMake(50, 50),
            CGPointMake(50, 50),CGPointMake(10, 50),
            CGPointMake(10, 50),CGPointMake(10, 10)
        };
        // 多点连线方法
        CGContextStrokeLineSegments(ct, points, 8);
    
    画弧线
    • 效果


      81AD6E35-A85A-42EF-967E-A79D52952DA7.png
    • 代码
      从当前点开始画,然后画一个圆角。
      两个点加上当前点计算圆角的两条切线,来确定圆角的角度。
      半径参数决定圆角的大小
        CGContextMoveToPoint(ct, 10, 10);
        CGContextAddArcToPoint(ct,80,10,80,30,20);
        CGContextAddLineToPoint(ct, 80, 110);
    
    画圆弧
    • 效果


      BB569983-B810-4089-890C-116ED2279AA9.png
    • 代码
    CGContextAddArc(ct, 30, 30, 20, 0, M_PI_2*3, 0);
    
    批量添加直线
    • 效果
      直线是连接着的,kCGLineJoinRound 设置后有连接样式改变


      24625B11-C3E2-4107-A735-27C73B33A7E2.png
    • 代码
    // 设置连接点为圆角
        CGContextSetLineJoin(ct, kCGLineJoinRound);
        CGPoint points[] = {
            CGPointMake(10, 10),
            CGPointMake(50, 10),
            CGPointMake(50, 50),
            CGPointMake(10, 50),
            
        };
      
        CGContextAddLines(ct, points, 4);
        CGContextClosePath(ct);
        CGContextStrokePath(ct);
    
    批量画直线

    只是单独的画很多直线,但是相互并没有连接,利用kCGLineJoinRound 设置后并没有任何反应。

    • 效果


      954AEE47-9A89-4050-B935-7D7E3DE3EC98.png
    • 代码
    // 设置连接点为圆角,但是这些点并没有连接
    CGContextSetLineJoin(ct, kCGLineJoinRound);
        CGPoint points[] = {
            CGPointMake(10, 10),CGPointMake(50, 10),
            CGPointMake(50, 10),CGPointMake(50, 50),
            CGPointMake(50, 50),CGPointMake(10, 50),
            CGPointMake(10, 50),CGPointMake(10, 10)
        };
        
        // 多点连线方法
        CGContextStrokeLineSegments(ct, points, 8);
    

    相关文章

      网友评论

          本文标题:CGContext-上下文(画布)的应用

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