iOS基础·OC高级篇我爱编程

CoreGraphics核心绘图总结

2018-04-16  本文已影响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;
@interface DrawTableViewCell : UITableViewCell
@property (copy,   nonatomic) void (^block)(UITableViewCell *cell);
+ (instancetype)cellWithTableView:(UITableView *)tableView;
@end
#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
#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
#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绘图操作为什么不会出现复用问题,一直没有找到合理的解释,后面会接着研究,还希望大神指点一二。

上一篇下一篇

猜你喜欢

热点阅读