标签:
基于C的API,用于绘图, 当使用UIKit来创建按钮、图像或者其他UIView的子类时,UIKit会使用Core Graphics来将这些元素绘制在屏幕上
可创建直线、路径、渐变、文字、图像等内容Context是图形上下文,可以将其理解为一块画布,我们可以在上面进行绘画操作,绘制完成后,将画布放到我们的view中显示即可,view看作是一个画框.
上下文属性:
路径(Path)
阴影(Shadow)
笔画(Stroke)
剪裁路径(Clip Path)
线条宽度(Line Width)
混合模式(Blend Mode)
填充颜色(Fill Color)
当前形变矩阵(Current Transform Matrix)
线条图案(Line Dash)
首先要明白current point的概念,在你调用CGContextMoveToPoint时,你其实是将一个点设置为current point,或者你调用了CGContextAddLineToPoint也同样在绘制线段后将current point修改为添加线段后的坐标点。
-
#import "ViewController.h" #import "CustomView.h" #import "GraphicsView.h" #import "DemoCGView.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; CustomView *view = [[CustomView alloc] initWithFrame:self.view.bounds]; // GraphicsView *view = [[GraphicsView alloc] initWithFrame:self.view.bounds]; [self.view addSubview:view]; } @end
#import <UIKit/UIKit.h> @interface CustomView : UIView @end
#import "CustomView.h" @implementation CustomView //- (instancetype) initWithFrame:(CGRect)frame { // if (self = [super initWithFrame:frame]) { // self.backgroundColor = [UIColor whiteColor]; // } // return self; // //} // 参考文章:http://blog.csdn.net/rhljiayou/article/details/9919713 - (void) drawRect:(CGRect)rect { [self drawString:@"Core Graphics绘图" frame:CGRectMake(100, 20, self.frame.size.width, 25)]; [self drawNullCircle]; // 空心圆 [self drawSolidCircle]; // 实心圆 [self drawCircle]; [self drawArc]; // 画弧线 [self drawLineSegment]; // 画线段 [self drawLineSegment2]; [self drawDashLine]; // 画虚线 [self drawDashLine2]; [self drawDashLine3]; [self drawSimpleRect]; // 画矩形 [self drawSimpleRect2]; [self drawFillRect]; [self drawFillStrokeRect]; [self drawRoundRect]; // 圆角矩形 [self drawEllipse]; // 画椭圆 [self drawTriangle]; // 画三角形 [self drawImage]; // 画图片 [self drawSmileFace]; // 画笑脸 [self drawFan]; // 画扇形 [self drawGradient]; // 渐变(图层编程) [self drawQuadCurve]; // 二次曲线 [self drawCurve]; // 三次曲线 [self drawGradient2]; // 渐变 } // 画字符串:直接使用NSString中的drawInRect:withFont 或 drawInRect:withAttributes方法即可 - (void)drawString:(NSString *)string frame:(CGRect)frame { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(context, 1.0, 0, 0, 1.0); // 红色 UIFont *font = [UIFont boldSystemFontOfSize:11.0]; CGContextSaveGState(context); CGContextSetShadow(context, CGSizeMake(10, 5), 2); // 阴影白色背景下才能看出效果,可以重写initWithFrame设置背景色白色 [string drawInRect:frame withAttributes:@{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor redColor]}]; // [string drawInRect:frame withFont:font]; CGContextRestoreGState(context); } // 画空心圆 // 画空心圆就是画一个完整的圆形的弧线,画弧线需要知道的参数: // 圆点(x, y) // 半径radius, 因画圆使用画弧的方法,所以还需要其他参数: // 开始弧度(startAngle), // 结束弧度(endAngle), 弧度=180°/π (≈57.3°) 度=弧度×180°/π 360°=360×π/180=2π 弧度 // 旋转方向clockwise:0:顺时针 1:逆时针 /* * 弧度的定义是:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆的半径时,两条射线的夹角大小为1弧度 * 弧度和角度的算法 参考文章:http://blog.chinaunix.net/uid-20622737-id-1913082.html * */ //void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise) // 以(110, 70)为圆心,半径25, 顺时针 从0弧度到2π弧度开始画弧, 0~2π弧度是一个完整的圆 - (void)drawNullCircle { CGContextRef context = UIGraphicsGetCurrentContext(); // 获取绘画的当前的上下文:即画布 CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); // 设置笔触颜色:白色 CGContextSetLineWidth(context, 1.0f); // 设置线的宽度 CGContextAddArc(context, 30, 70, 15, 0, 2 * M_PI, 0); // 添加弧度(弧度 0~2*M_PI即为 0~360度,即:一周) CGContextDrawPath(context, kCGPathStroke); // 绘制填充 路径绘画模式为:笔触模式 CGPathDrawingMode=kCGPathStroke } // 画实心圆 // 画空心圆只需要设置笔触颜色就可以了,画实心圆需要知道圆的内部颜色即填充颜色 路径绘画模式为:填充模式 CGPathDrawingMode=kCGPathFill - (void)drawSolidCircle { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); CGContextSetLineWidth(context, 1.0); CGContextAddArc(context, 90, 70, 25, 0, 2 * M_PI, 0); CGContextDrawPath(context, kCGPathFill); // 路径填充 } // 画圆:同时设置圆的边框border和填充颜色 - (void)drawCircle { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); CGContextSetLineWidth(context, 3.0); CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); CGContextAddArc(context, 160, 70, 30, 0, 2 * M_PI, 0); CGContextDrawPath(context, kCGPathFillStroke); // 路径填充笔触 } // 画弧线 - (void)drawArc { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); CGContextSetLineWidth(context, 3.0f); // CGContextAddArc(context, 320, 70, 30, 0, 2 * M_PI / 6 * 1, 0); // CGContextAddArc(context, 250, 70, 30, 2 * M_PI / 6 * 1, 2 * M_PI, 1); // CGContextAddArc(context, 220, 70, 30, 0, 1, 0); CGContextAddArc(context, 240, 70, 30, 2 * M_PI / 6 * 5, 2 * M_PI, 0); CGContextDrawPath(context, kCGPathStroke); } // 画线段:画线端需要两个端点即可(起点和终点) - (void) drawLineSegment { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor); CGContextSetLineWidth(context, 2.0f); // 起点和终点 CGPoint points[2] = {CGPointMake(10, 120), CGPointMake(60, 120)}; CGContextAddLines(context, points, 2); CGContextDrawPath(context, kCGPathStroke); } // 画线段,方式二 // void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y) - (void)drawLineSegment2 { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); CGContextSetLineWidth(context, 10); // 将坐标p1(x, y)设置为当前点即起点, 当前点可以理解上当前笔触所在的位置,类似于电脑上讲光标从一个位置移动到另一个位置 CGContextMoveToPoint(context, 70, 120); // 起点 CGContextAddLineToPoint(context, 140, 120); // 终点 CGContextClosePath(context); CGContextDrawPath(context, kCGPathStroke); } // 画虚线 // 直线可以看成由无数个小圆点....组成,这些圆点之间没有任何间隙,紧密挨着 - (void)drawDashLine { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextBeginPath(context); CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor); CGContextSetLineWidth(context, 2.0); CGFloat lengths[] = {1, 3}; //{小圆点,间隙点} 表示先绘制1个小圆点,然后再跳过3个小圆点作为间隙,接下拉再绘制一个小圆点,然后再跳过3个小圆点作为间隙,反复下去 //CGContextSaveGState 和CGContextRestoreGState的理解: // CGContextSaveGState是对当前上下文状态做个标记的开始,CGContextRestoreGState用于标记的结束,标记范围内 // 的修改只会对当前操作有效,对于标记之后是无效的。这样做的目的是放置当前的一些设置操作影响到接下来的操作 // 例如:本例中为context设置了虚线 CGContextSetLineDash,如果本例操作完后CGContextRestoreGState,对后面的例子没有任何影响 // 如果不加 CGContextSaveGState 和 CGContextRestoreGState,后面的绘图都变成虚线而不是实现了,因为所有绘图操作UIGraphicsGetCurrentContext()获得的是同一个实例 CGContextSaveGState(context); CGContextSetLineDash(context, 0, lengths, 2); CGContextMoveToPoint(context, 150, 120); // 起点 CGContextAddLineToPoint(context, 200, 120); // 终点 CGContextStrokePath(context); CGContextRestoreGState(context); } - (void)drawDashLine2 { // phase参数表示在第一个虚线绘制的时候跳过多少个点 CGContextRef context = UIGraphicsGetCurrentContext(); CGContextBeginPath(context); CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor); CGContextSetLineWidth(context, 2.0); CGFloat lengths[] = {10, 10}; CGContextSaveGState(context); CGContextSetLineDash(context, 5, lengths, 2); CGContextMoveToPoint(context, 210, 100); // 起点 CGContextAddLineToPoint(context, 355, 100); // 终点 CGContextStrokePath(context); CGContextRestoreGState(context); } - (void)drawDashLine3 { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextBeginPath(context); CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor); CGContextSetLineWidth(context, 2.0); CGFloat lengths[] = {5, 10, 10}; // 先绘制5个点,跳过10个点 绘制10个点,跳过5个点 绘制10个点,跳过10个点 如此反复下去 CGContextSaveGState(context); CGContextSetLineDash(context, 0, lengths, 3); CGContextMoveToPoint(context, 210, 120); // 起点 CGContextAddLineToPoint(context, 355, 120); // 终点 CGContextStrokePath(context); CGContextRestoreGState(context); } // 画矩形:知道起始点(x, y) 和 宽高 就可以了 // void CGContextAddRect(CGContextRef c, CGRect rect) - (void)drawSimpleRect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor); CGContextSetLineWidth(context, 2.0); CGContextAddRect(context, CGRectMake(10, 150, 60, 40)); CGContextDrawPath(context, kCGPathStroke); } // 画矩形:方式二 根据点点连线,根据这种方式可以画任意多边形 - (void)drawSimpleRect2 { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor); CGPoint points[5] = {CGPointMake(90, 150), CGPointMake(150, 150), CGPointMake(150, 190), CGPointMake(90, 190), CGPointMake(90, 150)}; CGContextAddLines(context, points, 5); CGContextDrawPath(context, kCGPathStroke); } // 画填充矩形 - (void)drawFillRect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [UIColor magentaColor].CGColor); CGContextSetLineWidth(context, 2.0); CGContextAddRect(context, CGRectMake(170, 150, 50, 30)); CGContextDrawPath(context, kCGPathFill); } - (void)drawFillStrokeRect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); CGContextSetFillColorWithColor(context, [UIColor purpleColor].CGColor); CGContextSetLineWidth(context, 2.0); CGContextAddRect(context, CGRectMake(240, 150, 50, 40)); CGContextDrawPath(context, kCGPathFillStroke); } // 对应CGContextAddArcToPoint方法的理解参考文章: http://blog.csdn.net/dick_china/article/details/7864428 // 参考文章: http://donbe.blog.163.com/blog/static/138048021201052093633776/ // void CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius) - (void)drawRoundRect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor); CGContextSetLineWidth(context, 3.0); float x = 330; float y = 150; float width = 60; float heigth = 40; float w = width / 2; float h = heigth / 2; // 设置当前点 CGContextMoveToPoint(context, x, y); CGContextAddArcToPoint(context, x - w, y, x - w, y + h, 10); CGContextAddArcToPoint(context, x - w, y + h + h, x, y + h + h, 10); CGContextAddArcToPoint(context, x + w, y + h + h, x + w, y + h, 10); CGContextAddArcToPoint(context, x + w, y, x, y, 10); CGContextClosePath(context); CGContextDrawPath(context, kCGPathStroke); } // 画椭圆:给定一个矩形范围,然后在矩形中画一个最大的椭圆 // void CGContextAddEllipseInRect(CGContextRef c, CGRect rect) - (void) drawEllipse { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); CGContextSetLineWidth(context, 2); CGContextAddEllipseInRect(context, CGRectMake(20, 230, 60, 30)); CGContextDrawPath(context, kCGPathStroke); } // 画三角形:知道三角形的三点坐标,然后连成线 即可, 和画线段、多边形原理一样 - (void)drawTriangle { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor brownColor].CGColor); CGContextSetLineWidth(context, 2); CGPoint points[3] = {CGPointMake(100, 260), CGPointMake(160, 260), CGPointMake(100, 200)}; CGContextAddLines(context, points, 3); CGContextClosePath(context); // 关闭路径的意思是 :将当前点和起点连接起来 将终点(100, 200) 和 起点(100, 260)进行连接起来, 如果不关闭路径也可以像drawSimpleRect2方法一样处理,既:将终点和起点再连线一下 CGContextDrawPath(context, kCGPathFillStroke); } // 画图片 - (void)drawImage { CGContextRef context = UIGraphicsGetCurrentContext(); UIImage *image = [UIImage imageNamed:@"1.jpeg"]; CGContextDrawImage(context, CGRectMake(20, 280, 50, 50), image.CGImage); } // 画笑脸 - (void) drawSmileFace { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor); CGContextSetLineWidth(context, 3); // 左面部分 CGContextMoveToPoint(context, 140, 280); CGContextAddArcToPoint(context, 120, 250, 100, 280, 25); CGContextStrokePath(context); // 右面部分 CGContextMoveToPoint(context, 200, 280); CGContextAddArcToPoint(context, 180, 250, 160, 280, 25); CGContextStrokePath(context); // 下面部分 CGContextMoveToPoint(context, 180, 320); CGContextAddArcToPoint(context, 150, 350, 120, 310, 30); CGContextStrokePath(context); } // 画扇形:其实就是画弧线CGContextAddArc,并使用填充笔触模式kCGPathFillStroke - (void)drawFan { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); CGContextMoveToPoint(context, 250, 340); CGContextAddArc(context, 250, 340, 80, -60*M_PI/180, -120*M_PI/180, 1); CGContextClosePath(context); CGContextDrawPath(context, kCGPathFillStroke); } // 渐变矩形:在指定区域CGRect画层,然后将层添加到UIView的层上面, - (void) drawGradient { CGRect frame = CGRectMake(290, 210, 70, 40); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor); CGContextSetLineWidth(context, 2.0); CGContextAddRect(context, frame); CGContextDrawPath(context, kCGPathStroke); // 渐变层 CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = frame; gradient.colors = @[(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 ]; // 将渐变层插入到view层的最上方 [self.layer insertSublayer:gradient atIndex:0]; } // 二次曲线 // void CGContextAddQuadCurveToPoint(CGContextRef c, CGFloat cpx, CGFloat cpy, CGFloat x, CGFloat y) // 控制点(cpx, cpy) 直线的终点坐标(x, y) - (void)drawQuadCurve { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); CGContextSetLineWidth(context, 2.0); CGContextMoveToPoint(context, 20, 450); CGContextAddQuadCurveToPoint(context, 80, 300, 160, 450); CGContextStrokePath(context); } // 三次曲线:一般是一条直线,然后定义几个控制点,使直线变完曲 // void CGContextAddCurveToPoint(CGContextRef c, CGFloat cp1x, CGFloat cp1y, CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y) // 控制点1(cp1x, cp1y) 控制点2(cp2x, cp2y) 直线的终点坐标(x, y) // 参考文章: http://donbe.blog.163.com/blog/static/138048021201052093633776/ - (void)drawCurve { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); CGContextSetLineWidth(context, 2.0); CGContextMoveToPoint(context, 180, 430); CGContextAddCurveToPoint(context, 250, 300, 280, 490, 370, 450); CGContextStrokePath(context); } // 画渐变 - (void) drawGradient2 { CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); CGFloat colors[] = { 1,1,1, 1.00, 1,1,0, 1.00, 1,0,0, 1.00, 1,0,1, 1.00, 0,1,1, 1.00, 0,1,0, 1.00, 0,0,1, 1.00, 0,0,0, 1.00, }; // 渐变圆 CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4)); CGColorSpaceRelease(rgb); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextDrawRadialGradient(context, gradient, CGPointMake(330, 300), 0, CGPointMake(330, 300), 30, kCGGradientDrawsBeforeStartLocation); // 渐变 CGContextSaveGState(context); CGContextMoveToPoint(context, 10, 500); CGContextAddLineToPoint(context, 200, 500); CGContextAddLineToPoint(context, 200, 650); CGContextAddLineToPoint(context, 10, 650); CGContextClip(context); // 不剪裁的话宽度会是整个屏幕宽 // 开始坐标和结束坐标是为了控制渐变的方向和形状 // void CGContextDrawLinearGradient(CGContextRef c, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options) // startPoint:开始渐变的起始位置,endPoint 开始渐变的结束位置 options:渐变的方向,开始坐标之前,还是结束位置之后开始渐变 CGContextDrawLinearGradient(context, gradient, CGPointMake(10, 500), CGPointMake(10, 650), kCGGradientDrawsBeforeStartLocation); CGContextRestoreGState(context); } @end
#import <UIKit/UIKit.h> @interface GraphicsView : UIView @end
#import "GraphicsView.h" @implementation GraphicsView - (instancetype) initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor whiteColor]; } return self; } // UIBezierPath 是对Core Graphics的封装 - (void)drawRect:(CGRect)rect { [self drawRoundRect]; //[self drawCustomPath]; } - (void) drawRoundRect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetShadow(context, CGSizeMake(0, 5), 10); CGRect myRect = CGRectMake(60, 80, 200, 200); UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:myRect cornerRadius:30]; [bezierPath fill]; //CGContextSaveGState(context); // 当我们绘制渐变时,会填满整个图形上下文,所以需要按照路径进行剪裁 [bezierPath addClip]; // 用圆角矩形路径对上下文进行剪切 // 绘制渐变,这个渐变会被限制在剪裁路径的范围内 CGContextDrawLinearGradient(context, [self _makeGradient], CGPointMake(0, 80), CGPointMake(0, 320), 0); //CGContextRestoreGState(context); // 绘制文字 CGContextSetRGBFillColor(context, 0, 0, 0, 1); [@"iOS 5 Core Frameworks" drawInRect:CGRectMake(0, 120, 320, 200) withFont:[UIFont boldSystemFontOfSize:48] lineBreakMode:UILineBreakModeClip alignment:UITextAlignmentCenter]; } - (void)drawCustomPath { CGContextRef context = UIGraphicsGetCurrentContext(); UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(160, 20)]; [path addLineToPoint:CGPointMake(260, 340)]; [path addArcWithCenter:CGPointMake(160, 340) radius:100 startAngle:0 endAngle:M_PI clockwise:YES]; [path closePath]; [path fill]; } - (CGGradientRef) _makeGradient { CGFloat colors[8] = {1, 1, 1, 1, 222.0f/255.0f, 169.0f/222.0f, 269.0f/255.0f, 1}; CGFloat colorStops[2] = {0.0, 1.0}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, colorStops, 2); CGColorSpaceRelease(colorSpace); return gradient; } @end
标签:
原文地址:http://blog.csdn.net/vbirdbest/article/details/51535810