CGContextRef
CGContextRef
即图形上下文。可以这么理解,我们绘图是需要一个载体或者说输出目标,它用来显示绘图信息,并且决定绘制的东西输出到哪个地方。可以形象的比喻context
就像一个“画板”,我们得把图形绘制到这个画板上。所以,绘图必须要先有context
。
CGContextRef的获取
当你子类化了一个UIView
并实现了自己的drawRect:
方法后,一旦drawRect:
方法被调用,Cocoa
就会为你创建一个图形上下文,此时你对图形上下文的所有绘图操作都会显示在UIView
上。
CGContextRef使用步骤
- 先在
drawRect
方法中获得上下文context
- 绘制图形(线,图形,图片等)
- 设置一些修饰属性
- 渲染到上下文,完成绘图
UIGraphics API介绍
- 获取上下文
CGContextRef __nullable UIGraphicsGetCurrentContext(void)
- 矩形填充
void UIRectFill(CGRect rect);
// 填充绘制使用指定的混合模式
void UIRectFillUsingBlendMode(CGRect rect, CGBlendMode blendMode);
- 矩形描边
void UIRectFrame(CGRect rect);
// 描边绘制使用指定的混合模式
void UIRectFrameUsingBlendMode(CGRect rect, CGBlendMode blendMode);
- 裁剪
void UIRectClip(CGRect rect);
CGContext API介绍
- 线宽
void CGContextSetLineWidth(CGContextRef cg_nullable c, CGFloat width)
- 终点类型
void CGContextSetLineCap(CGContextRef cg_nullable c, CGLineCap cap)
- 交叉点类型
void CGContextSetLineJoin(CGContextRef cg_nullable c, CGLineJoin join)
- 透明度
void CGContextSetAlpha(CGContextRef cg_nullable c, CGFloat alpha)
- 透明矩形区域
void CGContextClearRect(CGContextRef cg_nullable c, CGRect rect)
- 描边渲染
void CGContextStrokePath(CGContextRef cg_nullable c)
- 描边颜色
void CGContextSetStrokeColor(CGContextRef cg_nullable c,
const CGFloat * cg_nullable components)
- 填充渲染
void CGContextFillPath(CGContextRef cg_nullable c)
- 填充颜色
void CGContextSetFillColor(CGContextRef cg_nullable c,
const CGFloat * cg_nullable components)
- 裁剪
void CGContextClip(CGContextRef cg_nullable c)
- 闭合路径
void CGContextClosePath(CGContextRef cg_nullable c)
- 设置阴影
void CGContextSetShadowWithColor(CGContextRef cg_nullable c,
CGSize offset, CGFloat blur, CGColorRef __nullable color)
- 设置颜色渐变
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSArray* gradientColors = [NSArray arrayWithObjects:
(id)[UIColor whiteColor].CGColor,
(id)[UIColor blackColor].CGColor, nil];
CGFloat gradientLocations[] = {0, 1};
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)gradientColors, gradientLocations);
CGPoint startCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
CGFloat radius = MAX(CGRectGetHeight(rect), CGRectGetWidth(rect));
CGContextDrawRadialGradient(context, gradient, startCenter, 0, startCenter, radius, 0);
- 设置线性渐变
CGPoint startPoint = CGPointMake(0, 0);
CGPoint endPoint = CGPointMake(200, 200);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
绘制
- 画线
// 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// 2.画线
CGContextMoveToPoint(contextRef, 20, 80); // 起点
CGContextAddLineToPoint(contextRef, self.frame.size.width-20, 80); //终点
// 3.修饰
CGContextSetRGBStrokeColor(contextRef, 0, 1.0, 0, 1.0); // 颜色
CGContextSetLineCap(contextRef, kCGLineCapRound); // 起点和重点圆角
CGContextSetLineJoin(contextRef, kCGLineJoinRound); // 转角圆角
// 4.渲染
CGContextStrokePath(contextRef);
- 画矩形
/ 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// 2.画矩形
CGContextAddRect(contextRef, CGRectMake(50, 50, 100, 100));
// 3.修饰
[[UIColor greenColor] set]; // 颜色
// 4.渲染
CGContextFillPath(contextRef);
- 画圆
// 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// 2.根据矩形画圆(椭圆只是设置不同的长宽)
CGContextAddEllipseInRect(contextRef, CGRectMake(10, 10, 50, 50));
// 3.修饰
[[UIColor greenColor] set]; // 颜色
// 4.渲染
CGContextFillPath(contextRef);
- 画圆弧
// 1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// 2.画圆弧
/*
* 参数一: 上下文
* 参数二: 中心点x
* 参数三: 中心点y
* 参数四: 半径
* 参数五: 开始弧度
* 参数六: 结束弧度
* 参数七: 0为顺时针,1为逆时针
*/
CGContextAddArc(contextRef, 200, 200, 50, M_PI, M_PI_4, 0);
// 3.修饰
[[UIColor greenColor] set]; // 颜色
// 4.渲染
CGContextFillPath(contextRef);
- 绘制文字
- (void)drawRect:(CGRect)rect {
//1.获取当前上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//2.创建文字
NSString *str = @"纸巾艺术";
//设置字体样式
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
//NSFontAttributeName:字体大小
dict[NSFontAttributeName] = [UIFont systemFontOfSize:25];
//字体前景色
dict[NSForegroundColorAttributeName] = [UIColor blueColor];
//字体背景色
dict[NSBackgroundColorAttributeName] = [UIColor redColor];
//字体阴影
NSShadow *shadow = [[NSShadow alloc]init];
//阴影偏移量
shadow.shadowOffset = CGSizeMake(2, 2);
//阴影颜色
shadow.shadowColor = [UIColor greenColor];
//高斯模糊
shadow.shadowBlurRadius = 5;
dict[NSShadowAttributeName] = shadow;
//字体间距
dict[NSKernAttributeName] = @10;
//绘制到上下文
//从某一点开始绘制 默认 0 0点
// [str drawAtPoint:CGPointMake(100, 100) withAttributes:nil];
//绘制区域设置
[str drawInRect:rect withAttributes:dict];
//添加到上下文
CGContextStrokePath(contextRef);
}
- 绘制图片
- (void)drawRect:(CGRect)rect {
//1.获取当前的上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//2.加载图片
//我们这里只需要加载一次就够了,不需要多次加载,所以不应该保存这个缓存
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"222.png" ofType:nil]];
//绘制一个多大的图片,并且设置他的混合模式以及透明度
//Rect:大小位置
//blendModel:混合模式
//alpha:透明度
[image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1];
//添加到上下文
CGContextFillPath(contextRef);
}
重绘
- 必须通过调用
setNeedsDisplay
或者setNeedsDisplayInRect:
重绘。 - 不能使用
gestureRecognizer
,只能使用touchbegan
等方法来掉用setNeedsDisplay
实时刷新屏幕,setNeedsLayout
可以重新调用drawRect:
方法,实现重绘的功能。
压栈
-
CGContextSaveGState
压栈当前的绘制状态,当你在处理一个绘制context
并且只是想保存的它的时候,CGContextSaveGState(context)
将当前绘制状态压到一个context
维护的绘制状态的栈中。 -
UIGraphicsPushContext
压栈当前的绘制对象,生成新的绘制图层,当你需要在当前的context
去创建一个新的CGContextRef
,UIGraphicsPushContext(context)
将context
压到一个CGContextRefs
(使得context
成为current context
)的栈中。
- (void)drawRect:(CGRect)rect {
CGContextRef purple = UIGraphicsGetCurrentContext();
// 设置紫色
[[UIColor purpleColor] setStroke];
// 设置线宽10
CGContextSetLineWidth(purple, 10);
// 画线
CGContextMoveToPoint(purple, 50, 50);
CGContextAddLineToPoint(purple, 50, 200);
// 紫色CGContextRef保存到栈
CGContextSaveGState(purple);
// 重新设置颜色
[[UIColor redColor] setStroke];
// 重新设置线宽
CGContextSetLineWidth(purple, 1);
//把紫色的上下文从栈中取出来
CGContextRestoreGState(purple);
// 渲染
CGContextStrokePath(purple);
}
CGContextSaveGState
会保存上下文的信息,线宽、颜色、绘制信息等,取出上下文并使其恢复原样,重新设置并不会生效。
效果:紫色线,宽度10
- (void)drawRect:(CGRect)rect {
CGContextRef purple = UIGraphicsGetCurrentContext();
// 设置紫色
[[UIColor purpleColor] setStroke];
// 设置线宽10
CGContextSetLineWidth(purple, 10);
// 画线
CGContextMoveToPoint(purple, 50, 50);
CGContextAddLineToPoint(purple, 50, 200);
// 紫色CGContextRef保存到栈
UIGraphicsPushContext(purple);
// 重新设置颜色
[[UIColor redColor] setStroke];
// 重新设置线宽
CGContextSetLineWidth(purple, 1);
//把紫色的上下文从栈中取出来
UIGraphicsPopContext();
// 渲染
CGContextStrokePath(purple);
}
UIGraphicsPushContext
会保存上下文的信息,线宽、颜色、绘制信息等,取出的是一个全新的绘图上下文,重新设置会生效。
效果:红色线,宽度1
网友评论