CoreGraphics核心绘图总结
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)
简单演示
-
首先看一下代码展示效果
tableView截图
- 简单介绍一下实现思路:
(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绘图操作为什么不会出现复用问题,一直没有找到合理的解释,后面会接着研究,还希望大神指点一二。