CoreGraphics核心绘图总结

作者: 一个默默无闻的程序猿 | 来源:发表于2018-04-16 11:37 被阅读33次

    CoreGraphics 简介:

    CoreGraphics:核心绘图框架,类名以CG开头的都属于这个框架,它提供的都是C语言的接口,属于跨平台类库,可以应用于iOS和macOS系统,与UIKit区分。
    首先来看一下这个类库中都有哪些类,以便于对这个框架有一个整体的了解(甚至您会发现,自己还不知道平时用到的很多类都出自这个类库中)。
    来到CoreGraphics.h看一下CoreGraphics库所包含的类

     #include <CoreGraphics/CGBase.h>               定义类本库中的一些宏和配置
     #include <CoreGraphics/CGAffineTransform.h>    包含一些形变方法,比如我们经常用到的CGAffineTransformMake(
     #include <CoreGraphics/CGBitmapContext.h>      位图绘制环境
     #include <CoreGraphics/CGColor.h>              绘图颜色,区分UIColor、CIColor
     #include <CoreGraphics/CGColorConversionInfo.h>定义颜色的一组组件,带有指定如何解释它们的颜色空间。
     #include <CoreGraphics/CGColorSpace.h>         指定如何解释用于显示的颜色值的配置文件。
     #include <CoreGraphics/CGContext.h>            2D绘图会话
     #include <CoreGraphics/CGDataConsumer.h>       内存写入管理
     #include <CoreGraphics/CGDataProvider.h>       内存读取管理
     #include <CoreGraphics/CGError.h>              错误分析
     #include <CoreGraphics/CGFont.h>               2D绘图字体
     #include <CoreGraphics/CGFunction.h>           定义和使用回调函数的通用工具
     #include <CoreGraphics/CGGeometry.h>           2D几何原语的各种结构和相关函数。
     #include <CoreGraphics/CGGradient.h>           用于绘制径向和轴向渐变填充的颜色的平滑过渡的定义。
     #include <CoreGraphics/CGImage.h>              返回纹理的图像数据作为一个Quartz 2D图像。
     #include <CoreGraphics/CGLayer.h>              一个幕后上下文,用于重用以核心图形绘制的内容。
     #include <CoreGraphics/CGPDFArray.h>           封装了一个PDF数组的不透明类型。
     #include <CoreGraphics/CGPDFContentStream.h>   一种不透明的类型,它提供对描述PDF页面外观的数据的访问。
     #include <CoreGraphics/CGPDFContext.h>         操作PDF的会话
     #include <CoreGraphics/CGPDFDictionary.h>      封装了一个PDF字典的类型。
     #include <CoreGraphics/CGPDFDocument.h>        包含PDF的文档
     #include <CoreGraphics/CGPDFObject.h>          PDF实例化
     #include <CoreGraphics/CGPDFOperatorTable.h>   为PDF操作符存储回调函数的类型。
     #include <CoreGraphics/CGPDFPage.h>            一种表示PDF文档中的页面的类型。
     #include <CoreGraphics/CGPDFScanner.h>         解析PDF扫描对象的内容流。
     #include <CoreGraphics/CGPDFStream.h>          表示PDF流的类型。
     #include <CoreGraphics/CGPDFString.h>          表示PDF文档中的字符串的数据类型。
     #include <CoreGraphics/CGPath.h>               核心图形的路径。
     #include <CoreGraphics/CGPattern.h>            用于绘制图形路径的2D模式。
     #include <CoreGraphics/CGShading.h>            由您提供的自定义函数控制的颜色平滑过渡的定义,用于绘制径向和轴向渐变填充。
    

    以上类的解释大部分诗官方文档直译,翻译的有些拗口
    来到/CGContext.h中,常用的函数如下:
    返回CFTypeID

    CFTypeID CGContextGetTypeID(void)
    

    将当前图形状态推入堆栈。之后,您对图形状态所做的修改会影响随后的的描画操作,但不影响存储在栈堆中的拷贝。

    CGContextSaveGState(CGContextRef cg_nullable c)
    

    把栈堆顶部状态弹出,返回之前的图形状态。

    CGContextRestoreGState(CGContextRef cg_nullable c)
    

    分别在X轴方向缩放sx,在Y轴方向缩放sy

    CGContextScaleCTM(CGContextRef cg_nullable c,CGFloat sx, CGFloat sy)
    

    分别在X轴方向移动tx,在Y轴方向移动ty

    CGContextTranslateCTM(CGContextRef cg_nullable c,CGFloat tx, CGFloat ty)
    

    旋转角度 angle

    CGContextRotateCTM(CGContextRef cg_nullable c, CGFloat angle)
    

    使用 transform 变换矩阵对 CGContextRef 的坐标系统执行变换

    CGContextConcatCTM(CGContextRef cg_nullable c,CGAffineTransform transform)
    

    获取CGContextRef的坐标系统的变换矩阵。

    CGAffineTransform CGContextGetCTM(CGContextRef cg_nullable c)
    

    设置绘图的线宽

    CGContextSetLineWidth(CGContextRef cg_nullable c, CGFloat width)
    

    设置线的端点的样式

    CGContextSetLineCap(CGContextRef cg_nullable c, CGLineCap cap)
    

    设置接接线的样式

    CGContextSetLineJoin(CGContextRef cg_nullable c, CGLineJoin join)
    

    设置图像上下文中的连接线的斜接限制。

    CGContextSetMiterLimit(CGContextRef cg_nullable c, CGFloat limit)
    

    设置图形上下文中的虚线的模式。

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

    设置弯曲的路径中的图形上下文的准确性

    CGContextSetFlatness(CGContextRef cg_nullable c, CGFloat flatness)
    

    设置图形上下文的透明度

    CGContextSetAlpha(CGContextRef cg_nullable c, CGFloat alpha)
    

    设置回合模式

    CGContextSetBlendMode(CGContextRef cg_nullable c, CGBlendMode mode)
    

    开始一个新的路径,旧的路径被丢弃

    CGContextBeginPath(CGContextRef cg_nullable c)
    

    在一个新的点开始新的路径

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

    从当前点到指定点添加一条线

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

    从当前点到指定点添加第一条曲线

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

    贝塞尔曲线

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

    闭合路径

    CGContextClosePath(CGContextRef cg_nullable c)
    

    矩形

    CGContextAddRect(CGContextRef cg_nullable c, CGRect rect)
    

    多个矩形

    CGContextAddRects(CGContextRef cg_nullable c,
                                     const CGRect * __nullable rects, size_t count)
    

    多条线

    CGContextAddLines(CGContextRef cg_nullable c,
                                     const CGPoint * __nullable points, size_t count)
    

    画椭圆

    CGContextAddEllipseInRect(CGContextRef cg_nullable c, CGRect rect)
    

    圆,扇形

    CGContextAddArc(CGContextRef cg_nullable c, CGFloat x, CGFloat y,
                                   CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwi)
    

    画圆弧

    CGContextAddArcToPoint(CGContextRef cg_nullable c,
                                          CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius)
    

    添加路径

    CGContextAddPath(CGContextRef cg_nullable c,
                                    CGPathRef cg_nullable path)
    

    将路径替换为线路径

    CGContextReplacePathWithStrokedPath(CGContextRef cg_nullable c)
    

    判断路径是否为空

    bool CGContextIsPathEmpty(CGContextRef cg_nullable c)
    

    获取路径当前的点

    CGPoint CGContextGetPathCurrentPoint(CGContextRef cg_nullable c)
    

    返回路径的边界框

    CGRect CGContextGetPathBoundingBox(CGContextRef cg_nullable c)
    

    拷贝路径

    CGPathRef __nullable CGContextCopyPath(CGContextRef cg_nullable c)
    

    点是否包含在路径中

    bool CGContextPathContainsPoint(CGContextRef cg_nullable c,
                                              CGPoint point, CGPathDrawingMode mode)
    

    绘制路径

    CGContextDrawPath(CGContextRef cg_nullable c,
                                     CGPathDrawingMode mode)
    

    填充路径

    CGContextFillPath(CGContextRef cg_nullable c)
    

    奇偶填充路径

    CGContextEOFillPath(CGContextRef cg_nullable c)
    

    给路径画线

    CGContextStrokePath(CGContextRef cg_nullable c)
    

    填充矩形

    CGContextFillRect(CGContextRef cg_nullable c, CGRect rect)
    

    填充矩形组

    CGContextFillRects(CGContextRef cg_nullable c,
                                      const CGRect * __nullable rects, size_t count)
    

    矩形画线

    CGContextStrokeRect(CGContextRef cg_nullable c, CGRect rect)
    

    矩形画线并设置线宽

    CGContextStrokeRectWithWidth(CGContextRef cg_nullable c,
                                                CGRect rect, CGFloat width)
    

    清除矩形

    CGContextClearRect(CGContextRef cg_nullable c, CGRect rect)
    

    填充矩形内的椭圆

    CGContextFillEllipseInRect(CGContextRef cg_nullable c,
                                              CGRect rect)
    

    矩形内部椭圆画线

    CGContextStrokeEllipseInRect(CGContextRef cg_nullable c,
                                                CGRect rect)
    

    线段,点的数组

    CGContextStrokeLineSegments(CGContextRef cg_nullable c,
                                               const CGPoint * __nullable points, size_t count)
    

    根据图形上下文获取剪辑路径

    CGContextClip(CGContextRef cg_nullable c)
    

    使用奇偶填充规则决定剪辑路径

    CGContextEOClip(CGContextRef cg_nullable c)
    
    CGContextResetClip(CGContextRef c)
    
    CGContextClipToMask(CGContextRef cg_nullable c, CGRect rect,
                                       CGImageRef cg_nullable mask)
    
    CGRect CGContextGetClipBoundingBox(CGContextRef cg_nullable c)
    
    CGContextClipToRect(CGContextRef cg_nullable c, CGRect rect)
    
    CGContextClipToRects(CGContextRef cg_nullable c,
                                        const CGRect *  rects, size_t count)
    
    CGContextSetFillColorWithColor(CGContextRef cg_nullable c,
                                                  CGColorRef cg_nullable color)
    
    CGContextSetStrokeColorWithColor(CGContextRef cg_nullable c,
                                                    CGColorRef cg_nullable color)
    
    CGContextSetFillColorSpace(CGContextRef cg_nullable c,
                                              CGColorSpaceRef cg_nullable space)
    
    CGContextSetStrokeColorSpace(CGContextRef cg_nullable c,
                                                CGColorSpaceRef cg_nullable space)
    
    CGContextSetFillColor(CGContextRef cg_nullable c,
                                         const CGFloat * cg_nullable components)
    
    CGContextSetStrokeColor(CGContextRef cg_nullable c,
                                           const CGFloat * cg_nullable components)
    
    CGContextSetFillPattern(CGContextRef cg_nullable c,
                                           CGPatternRef cg_nullable pattern, const CGFloat * cg_nullable components)
    
    CGContextSetStrokePattern(CGContextRef cg_nullable c,
                                             CGPatternRef cg_nullable pattern, const CGFloat * cg_nullable components)
    
    CGContextSetPatternPhase(CGContextRef cg_nullable c, CGSize phase)
    
    CGContextSetGrayFillColor(CGContextRef cg_nullable c,
                                             CGFloat gray, CGFloat alpha)
    
    CGContextSetGrayStrokeColor(CGContextRef cg_nullable c,
                                               CGFloat gray, CGFloat alpha)
    
    CGContextSetRGBFillColor(CGContextRef cg_nullable c, CGFloat red,
                                            CGFloat green, CGFloat blue, CGFloat alpha)
    
    CGContextSetRGBStrokeColor(CGContextRef cg_nullable c,
                                              CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
    
    CGContextSetCMYKFillColor(CGContextRef cg_nullable c,
                                             CGFloat cyan, CGFloat magenta, CGFloat yellow, CGFloat black, CGFloat alpha)
    
    CGContextSetCMYKStrokeColor(CGContextRef cg_nullable c,
                                               CGFloat cyan, CGFloat magenta, CGFloat yellow, CGFloat black, CGFloat alpha)
    
    CGContextSetRenderingIntent(CGContextRef cg_nullable c,
                                               CGColorRenderingIntent intent)
    
    CGContextDrawImage(CGContextRef cg_nullable c, CGRect rect,
                                      CGImageRef cg_nullable image)
    
    CGContextDrawTiledImage(CGContextRef cg_nullable c, CGRect rect,
                                           CGImageRef cg_nullable image)
    
    CGInterpolationQuality CGContextGetInterpolationQuality(CGContextRef cg_nullable c)
    
    CGContextSetInterpolationQuality(CGContextRef cg_nullable c,
                                                    CGInterpolationQuality quality)
    
    CGContextSetShadowWithColor(CGContextRef cg_nullable c,
                                               CGSize offset, CGFloat blur, CGColorRef __nullable color)
    
    CGContextSetShadow(CGContextRef cg_nullable c, CGSize offset,
                                      CGFloat blur)
    
    CGContextDrawLinearGradient(CGContextRef cg_nullable c,
                                               CGGradientRef cg_nullable gradient, CGPoint startPoint, CGPoint endPoint,
                                               CGGradientDrawingOptions options)
    
    CGContextDrawRadialGradient(CGContextRef cg_nullable c,
                                               CGGradientRef cg_nullable gradient, CGPoint startCenter, CGFloat startRadius,
                                               CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options)
    
    CGContextDrawShading(CGContextRef cg_nullable c,
                                        cg_nullable CGShadingRef shading)
    
    CGContextSetCharacterSpacing(CGContextRef cg_nullable c,
                                                CGFloat spacing)
    
    CGContextSetTextPosition(CGContextRef cg_nullable c,
                                            CGFloat x, CGFloat y)
    
    CGPoint CGContextGetTextPosition(CGContextRef cg_nullable c)
    
    CGContextSetTextMatrix(CGContextRef cg_nullable c,
                                          CGAffineTransform t)
    
    CGAffineTransform CGContextGetTextMatrix(CGContextRef cg_nullable c)
    
    CGContextSetTextDrawingMode(CGContextRef cg_nullable c,
                                               CGTextDrawingMode mode)
    
    CGContextSetFont(CGContextRef cg_nullable c,
                                    CGFontRef cg_nullable font)
    
    CGContextSetFontSize(CGContextRef cg_nullable c, CGFloat size)
    CGContextShowGlyphsAtPositions(CGContextRef cg_nullable c,
                                                  const CGGlyph * cg_nullable glyphs, const CGPoint * cg_nullable Lpositions,
                                                  size_t count)
    
    CGContextDrawPDFPage(CGContextRef cg_nullable c,
                                        CGPDFPageRef cg_nullable page)
    
    CGContextBeginPage(CGContextRef cg_nullable c,
                                      const CGRect * __nullable mediaBox)
    
    CGContextEndPage(CGContextRef cg_nullable c)
    
    CGContextRef cg_nullable CGContextRetain(CGContextRef cg_nullable c)
    
    CGContextRelease(CGContextRef cg_nullable c)
    
    CGContextFlush(CGContextRef cg_nullable c)
    
    CGContextSynchronize(CGContextRef cg_nullable c)
    
    CGContextSetShouldAntialias(CGContextRef cg_nullable c,
                                               bool shouldAntialias)
    
    CGContextSetAllowsAntialiasing(CGContextRef cg_nullable c,
                                                  bool allowsAntialiasing)
    
    CGContextSetShouldSmoothFonts(CGContextRef cg_nullable c,
                                                 bool shouldSmoothFonts)
    
    CGContextSetAllowsFontSmoothing(CGContextRef cg_nullable c,
                                                   bool allowsFontSmoothing)
    
    CGContextSetShouldSubpixelPositionFonts(
                                                           CGContextRef cg_nullable c, bool shouldSubpixelPositionFonts)
    
    CGContextSetAllowsFontSubpixelPositioning(
                                                             CGContextRef cg_nullable c, bool allowsFontSubpixelPositioning)
    
    CGContextSetShouldSubpixelQuantizeFonts(
                                                           CGContextRef cg_nullable c, bool shouldSubpixelQuantizeFonts)
    
    CGContextSetAllowsFontSubpixelQuantization(
                                                              CGContextRef cg_nullable c, bool allowsFontSubpixelQuantization)
    
    CGContextBeginTransparencyLayer(CGContextRef cg_nullable c,
                                                   CFDictionaryRef __nullable auxiliaryInfo)
    
    CGContextBeginTransparencyLayerWithRect(
                                                           CGContextRef cg_nullable c, CGRect rect, CFDictionaryRef __nullable auxInfo)
    
    CGContextEndTransparencyLayer(CGContextRef cg_nullable c)
    
    CGAffineTransform CGContextGetUserSpaceToDeviceSpaceTransform(CGContextRef cg_nullable c)
    
    CGPoint CGContextConvertPointToDeviceSpace(CGContextRef cg_nullable c,
                                                         CGPoint point)
    
    CGPoint CGContextConvertPointToUserSpace(CGContextRef cg_nullable c,
                                                       CGPoint point)
    
    CGSize CGContextConvertSizeToDeviceSpace(CGContextRef cg_nullable c,
                                                       CGSize size)
    
    CGSize CGContextConvertSizeToUserSpace(CGContextRef cg_nullable c,
                                                     CGSize size)
    
    CGRect CGContextConvertRectToDeviceSpace(CGContextRef cg_nullable c,
                                                       CGRect rect)
    
    CGRect CGContextConvertRectToUserSpace(CGContextRef cg_nullable c,
                                                     CGRect rect)
    
    CGContextSelectFont(CGContextRef cg_nullable c,
                                       const char * cg_nullable name, CGFloat size, CGTextEncoding textEncoding)
    
    CGContextShowText(CGContextRef cg_nullable c,
                                     const char * cg_nullable string, size_t length)
    
    CGContextShowTextAtPoint(CGContextRef cg_nullable c,
                                            CGFloat x, CGFloat y, const char * cg_nullable string, size_t length)
    
    CGContextShowGlyphs(CGContextRef cg_nullable c,
                                       const CGGlyph * __nullable g, size_t count)
    
    CGContextShowGlyphsAtPoint(CGContextRef cg_nullable c, CGFloat x,
                                              CGFloat y, const CGGlyph * __nullable glyphs, size_t count)
    
    CGContextShowGlyphsWithAdvances(CGContextRef cg_nullable c,
                                                   const CGGlyph * __nullable glyphs, const CGSize * __nullable advances,
                                                   size_t count)
    
    CGContextDrawPDFDocument(CGContextRef cg_nullable c, CGRect rect,
                                            CGPDFDocumentRef cg_nullable document, int page)
    

    简单演示

    1. 首先看一下代码展示效果


      tableView截图
    视图层级
    1. 简单介绍一下实现思路:
      (1)每一种绘图方式放在一个cell中,直接在cell内部drawRect方法中实现绘图代码;
      (2)tableView的一个cell的数据通过block方式外面传入,也就是说在外面实现block,在cell的drawRect方法中回调block;
      (3)MVVC模式将tableView的数据block数组放在viewModel中处理直接返回数据数组;
      (4)实现每一种绘图代码block;
    • Cell.h
    @interface DrawTableViewCell : UITableViewCell
    @property (copy,   nonatomic) void (^block)(UITableViewCell *cell);
    + (instancetype)cellWithTableView:(UITableView *)tableView;
    @end
    
    • Cell.m
    #import "DrawTableViewCell.h"
    
    @implementation DrawTableViewCell
    
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
        if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
            self.backgroundColor = [UIColor whiteColor];
            self.selectionStyle = UITableViewCellSelectionStyleNone;
            //创建cell的子控件
        }
        return self;
    }
    - (void)drawRect:(CGRect)rect{
        if (self.block) {
            self.block(self);
        }
    }
    #pragma mark - 快速创建Cell
    + (instancetype)cellWithTableView:(UITableView *)tableView
    {
        static NSString *ID = @"DrawTableViewCell";
        DrawTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        if (cell == nil) {
            cell = [[DrawTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ID];
        }
        return cell;
    }
    - (void)setBlock:(void (^)(UITableViewCell *))block{
        _block = block;
        [self setNeedsDisplay];
    }
    
    @end
    
    • ViewController
    #import "ViewController.h"
    #import "ViewModel.h"
    #import "DrawTableViewCell.h"
    @interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
    @property (strong, nonatomic) UITableView *mainTableView;
    @property (strong, nonatomic) NSArray *dataArr;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.dataArr = [[ViewModel new] tableViewDatas];
        [self.view addSubview:self.mainTableView];
    //    [self saveViewImageToAlbum];
    }
    //将tableView截图保存到相册
    - (void)saveViewImageToAlbum{
        CGRect oldFrame = self.mainTableView.frame;
        self.mainTableView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 1600);
        UIGraphicsBeginImageContextWithOptions(self.mainTableView.frame.size, self.mainTableView.opaque, 1);
        [self.mainTableView.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
        self.mainTableView.frame = oldFrame;
    }
    #pragma mark --------UITableViewDelegate,UITableViewDataSource
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return 1;
    }
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return self.dataArr.count;
    }
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        return 200;
    }
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        DrawTableViewCell *cell = [DrawTableViewCell cellWithTableView:tableView];
        cell.block = self.dataArr[indexPath.row];
        return cell;
    }
    #pragma mark --------懒加载
    - (UITableView *)mainTableView{
        if (!_mainTableView) {
            _mainTableView = [[UITableView alloc]initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStyleGrouped];
            _mainTableView.delegate = self;
            _mainTableView.dataSource = self;
            //        _mainTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        }
        return _mainTableView;
    }
    - (NSArray *)dataArr{
        if (!_dataArr) {
            _dataArr = [NSArray array];
        }
        return _dataArr;
    }
    @end
    
    • 重点下面ViewModel绘图代码block实现
      ViewModel.h
    #import <Foundation/Foundation.h>
    
    @interface ViewModel : NSObject
    + (NSArray *)tableViewDatas;
    @end
    

    ViewModel.m

    #import <UIKit/UIKit.h>
    #import "ViewModel.h"
    #import <QuartzCore/QuartzCore.h>
    @implementation ViewModel
    + (NSArray *)tableViewDatas{
        NSMutableArray *arr = [NSMutableArray array];
    #pragma ======================================================= 画圆
        void (^drawArc)(UITableViewCell *cell) = ^(UITableViewCell *cell){//画圆
            /**
             ===============================>>绘制文字 drawInRect
             */
            [self drawText:@"画圆"];
            /**
             首先介绍一个枚举值
             kCGPathFill,           填充非零绕数规则
             kCGPathEOFill,         表示奇偶规则
             kCGPathStroke,         路径
             kCGPathFillStroke,     路劲填充
             kCGPathEOFillStroke    表示描线,不是填充
             这个值可以区分画一个边框(未填充)和填充以及填充类型的图形。
             */
            /**
             ===============================>>画一个边框圆    kCGPathStroke
             */
            //第一步:拿到画板
            CGContextRef context = UIGraphicsGetCurrentContext();
            //第二步:context 设置线(边框)的颜色 如果需要改变颜色就要设置,如果不设置,使用上次设置的颜色,在同一个View中 UIGraphicsGetCurrentContext()函数每次获取的 context都是同一个
            CGContextSetRGBStrokeColor(context, 0, 0, 1, 1.0);
            //第三步:设置线(边框)宽
            CGContextSetLineWidth(context, 1.0);
            //第四步:在画板上添加一个圆  AddArc
            /**
             (1).context
             (2).x y 为圆点原点
             (3).radius 半径
             (4).startAngle 开始角度
             (5).endAngle 结束角度
             (6).clockwise 0 为顺时针 1 为逆时针
             */
    
            CGContextAddArc(context, 80, 50, 25, 0, 2 * M_PI, 0);
            //第五步:开始画(绘制)kCGPathStroke 画线、不填充
            CGContextDrawPath(context, kCGPathStroke);
            /**
             kCGLineCapButt,
             kCGLineCapRound,
             kCGLineCapSquare
             */
            /**
             ================================>>画一个填充圆
             */
            //第二步:设置填充颜色
            CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
            //第四步:在画板上添加圆
            CGContextAddArc(context, 160, 50, 25, 0, 2 * M_PI, 0);
            //第五步:画圆,kCGPathFill 填充
            CGContextDrawPath(context, kCGPathFill);
            
            /**
             ===============================>>画一个带边框的填充圆
             */
            //第二步:设置线颜色和填充颜色
            CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
            CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);
            //第三步:设置线宽
            CGContextSetLineWidth(context, 3.0);
            //第四步:在画板上添加圆
            CGContextAddArc(context, 240, 50, 25, 0, 2 * M_PI, 0);
            //第五步:绘制  kCGPathFillStroke 边框加填充
            CGContextDrawPath(context, kCGPathFillStroke);
            /**
             ================================>>画一段文字 换行也会识别
             */
            NSString *str = @"kCGPathFill,\nkCGPathEOFill,\nkCGPathStroke,\nkCGPathStroke,\nkCGPathFillStroke,\nkCGPathEOFillStroke";
            [str drawInRect:CGRectMake(15, 120, 300, 80) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14],NSForegroundColorAttributeName:[UIColor redColor]}];
            NSString *text = @"填充非零绕数规则\n表示奇偶规则\n路径\n路劲填充\n表示描线,不是填充";
            [text drawInRect:CGRectMake(150, 120, 300, 80) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14],NSForegroundColorAttributeName:[UIColor redColor]}];
        };
        [arr addObject:drawArc];
        
    #pragma ======================================================= 画线
        void (^drawLine)(UITableViewCell *cell) = ^(UITableViewCell *cell){//画线
            /**
             ===============================>>绘制文字
             */
            [self drawText:@"画线和弧线"];
            /**
             ===============================>>画线
             */
            //第一步:拿到画板
            CGContextRef context = UIGraphicsGetCurrentContext();
            //第二步:准备画线的点
            CGPoint aPoints[2];//坐标点数组
            aPoints[0] = CGPointMake(100, 30);//坐标1
            aPoints[1] = CGPointMake(200, 30);//坐标2
            //第三步:设置线的颜色
            CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
            //第四步:在画板上添加一条线
            /**
             1.context
             2.points 坐标点数组
             3.cout 大小
             */
            CGContextAddLines(context, aPoints, 2);//添加线
            //第五步:绘制
            CGContextDrawPath(context, kCGPathStroke);//绘制路径
            
            /**
             =================================>>画笑脸弧线
             */
            //左边
            CGContextSetRGBStrokeColor(context, 0, 1, 0.5, 1.0);
            CGContextMoveToPoint(context, 220, 25);//开始坐标p1
            /**
             1.context
             2.x1,y1跟p1形成一条线的坐标p2,x2,y2结束坐标跟p3形成一条线的p3,
             3.radius半径,注意, 需要算好半径的长度,
             
             */
            CGContextAddArcToPoint(context, 228, 13, 236, 25, 10);
            CGContextDrawPath(context, kCGPathStroke);
            
            //右边
            CGContextMoveToPoint(context, 240, 25);//开始坐标p1
            CGContextAddArcToPoint(context, 248, 13, 256, 25, 10);
            CGContextStrokePath(context);
            //下边
            CGContextMoveToPoint(context, 230, 35);//开始坐标p1
            CGContextAddArcToPoint(context, 238, 42, 246, 35, 10);
            CGContextStrokePath(context);
            /**
             ===============================>>绘制文字
             */
            NSString *text = @"画圆弧需注意:\n1.context\n2.x1,y1跟p1形成一条线的坐标p2,x2,y2结束坐标跟p3形成一条线的p3,\n3.radius半径,注意, 需要算好半径的长度,";
            [text drawInRect:CGRectMake(15, 80, 300, 120) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14],NSForegroundColorAttributeName:[UIColor redColor]}];
        };
        [arr addObject:drawLine];
        
    #pragma ======================================================= 绘制矩形以及渐变色填充
        void (^drawRec)(UITableViewCell *cell) = ^(UITableViewCell *cell){//矩形
            /**
             ===============================>>绘制文字
             */
            [self drawText:@"画矩形"];
            /**
             ================================>>画一个矩形
             */
            CGContextRef context = UIGraphicsGetCurrentContext();
    
            //画方框
            CGContextSetStrokeColorWithColor(context, [UIColor orangeColor].CGColor);
            CGContextStrokeRect(context, CGRectMake(60, 10, 50, 50));
            /**
             ================================>>画一个填充矩形
             */
            CGContextSetFillColorWithColor(context, [UIColor cyanColor].CGColor);
            CGContextFillRect(context, CGRectMake(120, 10, 50, 50));
            /**
             ================================>>画一个渐变色填充矩形
             */
            /**接下来介绍几种填充渐变色的方式 第一种 是在 QuartzCore 框架下得实现方式,第二种才是 CoreGraphics方式,虽然都能实现渐变色,但是两种截然不同的东西*/
            /**
             第一种填充方式必须导入quartcore #import <QuartzCore/QuartzCore.h>,这个就不属于在context上画,而是将层插入到view层上面。那么这里就设计到Quartz Core 图层编程了。
             */
            CAGradientLayer *gradient1 = [CAGradientLayer layer];
            gradient1.frame = CGRectMake(300, 10, 50, 50);
            gradient1.colors = @[(id)[UIColor whiteColor].CGColor,
                                 (id)[UIColor grayColor].CGColor,
                                 (id)[UIColor blackColor].CGColor,
                                 (id)[UIColor yellowColor].CGColor,
                                 (id)[UIColor blueColor].CGColor,
                                 (id)[UIColor redColor].CGColor,
                                 (id)[UIColor greenColor].CGColor,
                                 (id)[UIColor orangeColor].CGColor,
                                 (id)[UIColor brownColor].CGColor];
            [cell.layer insertSublayer:gradient1 atIndex:0];
            NSLog(@"%@",cell.layer.sublayers);
            /**
             第二种填充方式 CGGradientRef
             */
            CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
            CGFloat colors[] = {
                1,1,1,1.0,
                1,1,0,1.0,
                1,0,0,1.0,
                1,0,1,1.0,
                0,1,1,1.0,
                0,1,0,1.0,
                0,0,1,1.0,
                0,0,0,1.0,
            };
            CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0]) * 4));//形成梯形渐变效果
            CGColorSpaceRelease(rgb);
            //画线形成一个矩形
            //CGContextSaveGState 与 CGContextRestoreGState 的作用
            /**
             CGContextSaveGState 函数的作用是将当前图形状态推入堆栈。之后,您对图形状态所做的修改会影响随后的的描画操作,但不影响存储在栈堆中的拷贝。在修改完成后,您可以通过 CGContextRestoreGState 函数把栈堆顶部状态弹出,返回之前的图形状态。这种推入和弹出的方式是回到之前图形状态的快速方法,避免逐个撤销所有的状态修改;这也是将某些状态(比如裁剪路径)恢复到原有设置的唯一方式。
             */
            CGContextSaveGState(context);
            CGContextMoveToPoint(context, 190, 10);
            CGContextAddLineToPoint(context, 240, 10);
            CGContextAddLineToPoint(context, 240, 65);
            CGContextAddLineToPoint(context, 190, 65);
            CGContextClip(context);//contenxt 裁剪路径,后续操作的路径
            CGContextDrawLinearGradient(context, gradient, CGPointMake(190, 10), CGPointMake(190, 65), kCGGradientDrawsAfterEndLocation);
            CGContextRestoreGState(context);
            
            /**
             下面再看一个颜色渐变的圆
             */
            CGContextDrawRadialGradient(context, gradient, CGPointMake(260, 20), 0, CGPointMake(260, 20), 20, kCGGradientDrawsBeforeStartLocation);
            
            CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
            /**
             ===============================>>绘制文字
             */
            [@"CGContextSaveGState 函数的作用是将当前图形状态推入堆栈。之后,您对图形状态所做的修改会影响随后的的描画操作,但不影响存储在栈堆中的拷贝。在修改完成后,您可以通过 CGContextRestoreGState 函数把栈堆顶部状态弹出,返回之前的图形状态。这种推入和弹出的方式是回到之前图形状态的快速方法,避免逐个撤销所有的状态修改;这也是将某些状态(比如裁剪路径)恢复到原有设置的唯一方式。" drawInRect:CGRectMake(15, 70, [UIScreen mainScreen].bounds.size.width - 30, 140) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14],NSForegroundColorAttributeName:[UIColor redColor]}];
            
        };
        [arr addObject:drawRec];
        
    #pragma ======================================================= 绘制椭圆
        void (^drawEllipse)(UITableViewCell *cell) = ^(UITableViewCell *cell){//椭圆
            /**
             ===============================>>绘制文字
             */
            [self drawText:@"画扇形和椭圆"];
            /**
             ===============================>>画一个扇形
             */
            CGContextRef context = UIGraphicsGetCurrentContext();
            //画扇形,也就是画圆,只不过是设置角度的大小,形成一个扇形
            CGContextSetFillColorWithColor(context, [UIColor magentaColor].CGColor);
            CGContextMoveToPoint(context, 125, 45);
            CGContextAddArc(context, 125, 45, 35, - M_PI_4, - 3 * M_PI_4, 1);
            CGContextClosePath(context);
            CGContextDrawPath(context, kCGPathFillStroke);//绘制路径
            /**
             ================================>>画椭圆
             */
            CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);
            CGContextAddEllipseInRect(context, CGRectMake(195, 10, 50, 40));
            CGContextDrawPath(context, kCGPathFillStroke);
            /**
             ===============================>>绘制文字
             */
            [@"画扇形其实就是画圆,只不过是设置角度大小形成一个扇形;\n CGContextAddEllipseInRect函数画椭圆" drawInRect:CGRectMake(15, 70, [UIScreen mainScreen].bounds.size.width - 30, 140) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14],NSForegroundColorAttributeName:[UIColor redColor]}];
    
        };
        [arr addObject:drawEllipse];
        
    #pragma ======================================================= 画圆角矩形
        void (^drawRaAr)(UITableViewCell *cell) = ^(UITableViewCell *cell){
            /**
             ===============================>>绘制文字
             */
            [self drawText:@"画圆角矩形"];
            /**
             ===============================>>画一个圆角矩形
             */
            CGContextRef context = UIGraphicsGetCurrentContext();
            float fw = 220;
            float fh = 70;
            CGContextMoveToPoint(context, fw, fh - 20);//开始坐标
            CGContextAddArcToPoint(context, fw, fh, fw - 20, fh, 10);//右下角角度
            CGContextAddArcToPoint(context, 120, fh, 120, fh - 20, 10);//左下角角度
            CGContextAddArcToPoint(context, 120, 20, 120 + 20, 20, 10);//左上角角度
            CGContextAddArcToPoint(context, fw, 20, fw, 40, 10);//右上角角度
            CGContextClosePath(context);
            CGContextDrawPath(context, kCGPathFillStroke);
        };
        [arr addObject:drawRaAr];
        
    #pragma ======================================================= 三角形
        void (^drawThree)(UITableViewCell *cell) = ^(UITableViewCell *cell){//三角形
            /**
             ===============================>>绘制文字
             */
            [self drawText:@"画三角形"];
            /**
             ================================画一个三角形
             */
            CGContextRef context = UIGraphicsGetCurrentContext();
            /**
             画三角形只需要知道三个点,把三个点连起来
             */
            CGPoint points[3];
            points[0] = CGPointMake(200, 50);
            points[1] = CGPointMake(100, 150);
            points[2] = CGPointMake(300, 150);
            CGContextSetFillColorWithColor(context, [UIColor cyanColor].CGColor);
            CGContextSetLineWidth(context, 3.0);
            CGContextAddLines(context, points, 3);//添加线
            CGContextClosePath(context);
            CGContextDrawPath(context, kCGPathFillStroke);
        };
        [arr addObject:drawThree];
        
    #pragma ======================================================= 贝塞尔
        void (^drawQua)(UITableViewCell *cell) = ^(UITableViewCell *cell){
            /**
             ===============================>>绘制文字
             */
            [self drawText:@"画贝塞尔曲线"];
            /**
             ================================>>二次曲线
             */
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSetStrokeColorWithColor(context, [UIColor orangeColor].CGColor);
            CGContextMoveToPoint(context, 15, 60);
            CGContextAddQuadCurveToPoint(context, 155, 120, 300, 40);//设置贝塞尔曲线的控制点和终点坐标
            CGContextStrokePath(context);
            /**
             ===================================三次曲线
             */
            CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);
            CGContextMoveToPoint(context, 15, 150);
            CGContextAddCurveToPoint(context, 100, 20, 100, 120, 300, 150);//设置两个控制点和终点
            CGContextStrokePath(context);
        };
        [arr addObject:drawQua];
        
    #pragma ======================================================= 图片
        void (^drawImg)(UITableViewCell *cell) = ^(UITableViewCell *cell){//图片
            /**
             ===============================>>绘制文字
             */
            [self drawText:@"图片"];
            /**
             =================================绘制五张图片
             */
            CGContextRef context = UIGraphicsGetCurrentContext();
    
            for (int i = 1; i <= 5; i ++) {
                UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"code0%d",i]];
                [image drawInRect:CGRectMake(15 + (i - 1) * 60, 50, 50, 50)];
                CGContextDrawImage(context, CGRectMake(15 + (i - 1) * 60, 50, 50, 50), image.CGImage);
            }
            
        };
        [arr addObject:drawImg];
        return arr;
    }
    + (void)drawText:(NSString *)str{
        [str drawInRect:CGRectMake(15, 30, 90, 20) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14],NSForegroundColorAttributeName:[UIColor redColor]}];
    }
    

    遇到问题

    CoreGraphics绘图在tableView中不会出现复用问题,而QuartzCore CAGradientLayer 插入layer层会产生复用问题:


    QuartzCore填充部分被复用1
    QuartzCore填充部分被复用2

    CAGradientLayer 在layer层插入导致复用的问题能够知道原因:
    打印cell的layer.subLayers

    2018-04-16 10:40:03.694991+0800 Graphics[71486:5784058] (
        "<CAGradientLayer: 0x100dd91e0>",
        "<CALayer: 0x100ac4610>",
        "<CALayer: 0x100ac5100>"
    )
    

    CAGradientLayer 插入后一直会存在layer层中所以会被复用;
    然而CoreGraphics绘图操作为什么不会出现复用问题,一直没有找到合理的解释,后面会接着研究,还希望大神指点一二。

    相关文章

      网友评论

        本文标题:CoreGraphics核心绘图总结

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