前面我們講了UIBezierPath繪圖,UIBezierPath只能畫線,描繪幾何圖形。CGContextRef相當(dāng)于一個畫布,可以繪制任意圖形。
文字、圓、直線、弧線、矩形、扇形、橢圓、三角形、圓角矩形、圖片
前文回顧:
iOS-貝塞爾曲線(UIBezierPath)的基本使用
iOS-貝塞爾曲線(UIBezierPath)詳解(CAShapeLayer)
iOS-UIBezierPath動畫之果凍動畫
我們通過幾個例子來介紹CGContextRef的常用方法!
繪制一條折線
先看效果圖:

- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
//獲得處理的上下文
CGContextRef context = UIGraphicsGetCurrentContext();
//設(shè)置線條樣式
CGContextSetLineCap(context, kCGLineCapSquare);
//設(shè)置線條粗細寬度
CGContextSetLineWidth(context, 3.0);
//設(shè)置顏色
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
//開始一個起始路徑
CGContextBeginPath(context);
//起始點設(shè)置為(100, 100)
CGContextMoveToPoint(context, 100, 100);
//設(shè)置下一個坐標點
CGContextAddLineToPoint(context, 200, 200);
//設(shè)置下一個坐標點
CGContextAddLineToPoint(context, 100, 250);
//設(shè)置下一個坐標點
CGContextAddLineToPoint(context, 150, 280);
//連接上面定義的坐標點
CGContextStrokePath(context);
}
-
UIGraphicsGetCurrentContext()開啟上下文,可以理解為打開一個畫布。 -
CGContextBeginPath開始一個起始路徑 -
CGContextMoveToPoint起始點設(shè)置 -
CGContextMoveToPoint連接下一個坐標點 -
CGContextAddLineToPoint繪制虛線終點
畫一條虛線
先看效果

- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
//設(shè)置虛線顏色
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
//設(shè)置虛線寬度
CGContextSetLineWidth(context, 1);
//設(shè)置虛線繪制起點
CGContextMoveToPoint(context, 0, 110);
//設(shè)置虛線繪制終點
CGContextAddLineToPoint(context, self.frame.origin.x + self.frame.size.width, 110);
//設(shè)置虛線排列的寬度間隔:下面的arr中的數(shù)字表示先繪制3個點再繪制1個點
CGFloat arr[] = {3,1};
//下面最后一個參數(shù)“2”代表排列的個數(shù)。
CGContextSetLineDash(context, 0, arr, 2);
CGContextDrawPath(context, kCGPathStroke);
}
從代碼可以看出來CGContextRef還是寫在方法- (void)drawRect:(CGRect)rect里面。
-
UIGraphicsGetCurrentContext()開啟上下文,可以理解為打開一個畫布。 -
CGContextSetStrokeColorWithColor設(shè)置虛線顏色 -
CGContextSetLineWidth設(shè)置線條寬度 -
CGContextMoveToPoint(context, 0, 110)設(shè)置虛線繪制起點 -
CGContextAddLineToPoint繪制虛線終點 -
CGContextSetLineDash繪制虛線的間隔
方法名:CGContextSetLineDash(CGContextRef cg_nullable c, CGFloat phase, const CGFloat * __nullable lengths, size_t count)
- lengths的值{10,10}表示先繪制10個點,再跳過10個點,如此反復(fù)。
- 如果把lengths值改為{10, 20, 10},則表示先繪制10個點,跳過20個點,繪制10個點,跳過10個點,再繪制20個點,如此反復(fù)。
-
phase參數(shù)表示在第一個虛線繪制的時候跳過多少個點 -
count表示lengths的長度(個數(shù))
more:關(guān)于CGContextSetLineDash的使用方法,如果還不清楚,可以參考一個文章:繪制虛線 CGContextSetLineDash的使用,我覺得寫的不錯。
繪制多條線段
先看效果圖:

使用方法如下:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef ctx = UIGraphicsGetCurrentContext();
//設(shè)置畫筆屬性
CGContextSetStrokeColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextSetFillColorWithColor(ctx, [UIColor clearColor].CGColor);
CGContextSetLineWidth(ctx, 1);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGPoint point = CGPointMake(kScreenWidth/2, kScreenWidth/2);
CGContextMoveToPoint(ctx, kScreenWidth/2, kScreenWidth/2-100);
CGContextAddLineToPoint(ctx, point.x, point.y);
CGContextMoveToPoint(ctx, kScreenWidth/2-100, kScreenWidth/2);
CGContextAddLineToPoint(ctx, point.x, point.y);
CGContextMoveToPoint(ctx, kScreenWidth/2+50, kScreenWidth/2+50);
CGContextAddLineToPoint(ctx, point.x, point.y);
CGContextMoveToPoint(ctx, kScreenWidth/2+100, kScreenWidth/2-50);
CGContextAddLineToPoint(ctx, point.x, point.y);
CGContextStrokePath(ctx);
}
-
CGContextSetLineJoin設(shè)置線條拐點的樣式
從代碼可以看出來,我們可以在一個畫板里面繪制多條直線。
可以利用這個特性,繪制一些圖表:分布圖。。。
文字繪制
系統(tǒng)提供了繪制文字的兩個方法:
- (void)drawAtPoint:(CGPoint)point withAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs API_AVAILABLE(macos(10.0), ios(7.0));
- (void)drawInRect:(CGRect)rect withAttributes:(nullable NSDictionary<NSAttributedStringKey, id> *)attrs API_AVAILABLE(macos(10.0), ios(7.0));
效果圖如下:

使用方法如下:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
/*寫文字*/
CGContextSetRGBFillColor (context, 1, 0, 0, 1.0);//設(shè)置填充顏色
UIFont *font = [UIFont boldSystemFontOfSize:15.0];//設(shè)置
NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:15], NSForegroundColorAttributeName:[UIColor whiteColor]};
[@"這是一條文字:" drawInRect:CGRectMake(110, 120, 180, 20) withAttributes:attributes];
[@"畫線及孤線:" drawInRect:CGRectMake(110, 180, 100, 20) withAttributes:@{NSFontAttributeName:font}];
CGContextStrokePath(context);
}
畫圓
我們會發(fā)現(xiàn)CGContextRef和貝塞爾曲線的畫法,有相似之處。
畫圓也是,效果圖如下:

- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
//邊框圓
CGContextSetRGBStrokeColor(context,1,1,1,1.0);//畫筆線的顏色
CGContextSetLineWidth(context, 1.0);//線的寬度
//void CGContextAddArc(CGContextRef c,CGFloat x, CGFloat y,CGFloat radius,CGFloat startAngle,CGFloat endAngle, int clockwise)1弧度=180°/π (≈57.3°) 度=弧度×180°/π 360°=360×π/180 =2π 弧度
// x,y為圓點坐標,radius半徑,startAngle為開始的弧度,endAngle為 結(jié)束的弧度,clockwise 0為順時針,1為逆時針。
CGContextAddArc(context, 100, 120, 15, 0, 2 * M_PI, 0); //添加一個圓
CGContextDrawPath(context, kCGPathStroke); //繪制路徑
//填充圓,無邊框
CGContextAddArc(context, 150, 130, 30, 0, 2*M_PI, 0); //添加一個圓
CGContextDrawPath(context, kCGPathFill);//繪制填充
//畫大圓并填充顏
UIColor *aColor = [UIColor colorWithRed:1 green:0.0 blue:0 alpha:1];
CGContextSetFillColorWithColor(context, aColor.CGColor);//填充顏色
CGContextSetLineWidth(context, 3.0);//線的寬度
CGContextAddArc(context, 250, 140, 40, 0, 2*M_PI, 0); //添加一個圓
//kCGPathFill填充非零繞數(shù)規(guī)則,kCGPathEOFill表示用奇偶規(guī)則,kCGPathStroke路徑,kCGPathFillStroke路徑填充,kCGPathEOFillStroke表示描線,不是填充
CGContextDrawPath(context, kCGPathFillStroke); //繪制路徑加填充
CGContextStrokePath(context);
}
-
CGContextAddArc繪制圓的關(guān)鍵代碼。方法全名:CGContextAddArc(CGContextRef cg_nullable c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
各參數(shù):
-
(x, y)表示圓的中心點 -
startAngle起始角度 -
endAngle結(jié)束角度 -
clockwise順時針/逆時針
-
CGContextSetFillColorWithColor表示填充顏色
畫直線
剛剛畫折線的方法就可以畫直線,即:CGContextAddLineToPoint方法。
但是還有一種更特殊的方法,可以畫直線。
效果圖:

使用方法如下:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
//畫線
CGContextSetRGBStrokeColor(context, 1, 1, 1, 1);//改變畫筆顏色
CGPoint aPoints[2];//坐標點
aPoints[0] = CGPointMake(100, 80);//坐標1
aPoints[1] = CGPointMake(230, 80);//坐標2
//CGContextAddLines(CGContextRef c, const CGPoint points[],size_t count)
//points[]坐標數(shù)組,和count大小
CGContextAddLines(context, aPoints, 2);//添加線
CGContextDrawPath(context, kCGPathStroke); //根據(jù)坐標繪制路徑
}
-
CGContextAddLines繪制數(shù)組中的點。方法全名CGContextAddLines(CGContextRef cg_nullable c, const CGPoint * __nullable points, size_t count)
參數(shù)points表示一個點的集合
參數(shù)count表示點的個數(shù)
more:思考一下,如果這個集合里面有多個點,會怎么樣?評論區(qū)留言喲~
畫曲線
我們畫一個笑臉,還看看曲線怎么畫?
效果圖:

這個笑臉就是單個曲線組合而成。
使用方法如下:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
//畫笑臉弧線
//左
CGContextSetRGBStrokeColor(context, 1, 1, 1, 1);//改變畫筆顏色
CGContextMoveToPoint(context, 140, 80);//開始坐標p1
//CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,CGFloat x2, CGFloat y2, CGFloat radius)
//x1,y1跟p1形成一條切線(切點p2),x2,y2跟x1,y1形成一條切線(切點p3),radius半徑,注意, 需要算好半徑的長度,
CGContextAddArcToPoint(context, 148, 68, 156, 80, 10);
CGContextStrokePath(context);//繪畫路徑
//右
CGContextMoveToPoint(context, 160, 80);//開始坐標p1
//CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,CGFloat x2, CGFloat y2, CGFloat radius)
//x1,y1跟p1形成一條切線(切點p2),x2,y2跟x1,y1形成一條切線(切點p3),radius半徑,注意, 需要算好半徑的長度,
CGContextAddArcToPoint(context, 168, 68, 176, 80, 10);
CGContextStrokePath(context);//繪畫路徑
//下
CGContextMoveToPoint(context, 150, 90);//開始坐標p1
//CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,CGFloat x2, CGFloat y2, CGFloat radius)
//x1,y1跟p1形成一條切線(切點p2),x2,y2跟x1,y1形成一條切線(切點p3),radius半徑,注意, 需要算好半徑的長度,
CGContextAddArcToPoint(context, 158, 102, 166, 90, 10);
CGContextStrokePath(context);
}
CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,CGFloat x2, CGFloat y2, CGFloat radius): x1,y1跟p1形成一條切線(切點p2),x2,y2跟x1,y1形成一條切線(切點p3),radius半徑。注意: 需要算好半徑的長度,
填充顏色
我們畫一個矩形,填充純色和漸變色。效果圖如下:

- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
/*畫矩形*/
CGContextStrokeRect(context,CGRectMake(100, 120, 10, 10));//畫方框
CGContextFillRect(context,CGRectMake(120, 120, 10, 10));//填充框
//矩形,并填棄顏色
CGContextSetLineWidth(context, 2.0);//線的寬度
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);//填充顏色
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);//線框顏色
CGContextAddRect(context,CGRectMake(140, 120, 60, 30));//畫方框
CGContextDrawPath(context, kCGPathFillStroke);//繪畫路徑
//矩形,并填棄漸變顏色
//第一種填充方式,第一種方式必須導(dǎo)入類庫quartcore并#import <QuartzCore/QuartzCore.h>,這個就不屬于在context上畫,而是將層插入到view層上面。那么這里就設(shè)計到Quartz Core 圖層編程了。
CAGradientLayer *gradient1 = [CAGradientLayer layer];
gradient1.frame = CGRectMake(240, 120, 60, 30);
gradient1.colors = [NSArray arrayWithObjects:(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,nil];
[self.layer insertSublayer:gradient1 atIndex:0];
//第二種填充方式
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);
//畫線形成一個矩形
//CGContextSaveGState與CGContextRestoreGState的作用
/*
CGContextSaveGState函數(shù)的作用是將當(dāng)前圖形狀態(tài)推入堆棧。之后,您對圖形狀態(tài)所做的修改會影響隨后的描畫操作,但不影響存儲在堆棧中的拷貝。在修改完成后,您可以通過CGContextRestoreGState函數(shù)把堆棧頂部的狀態(tài)彈出,返回到之前的圖形狀態(tài)。這種推入和彈出的方式是回到之前圖形狀態(tài)的快速方法,避免逐個撤消所有的狀態(tài)修改;這也是將某些狀態(tài)(比如裁剪路徑)恢復(fù)到原有設(shè)置的唯一方式。
*/
CGContextSaveGState(context);
CGContextMoveToPoint(context, 220, 90);
CGContextAddLineToPoint(context, 240, 90);
CGContextAddLineToPoint(context, 240, 110);
CGContextAddLineToPoint(context, 220, 110);
CGContextClip(context);//context裁剪路徑,后續(xù)操作的路徑
//CGContextDrawLinearGradient(CGContextRef context,CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint,CGGradientDrawingOptions options)
//gradient漸變顏色,startPoint開始漸變的起始位置,endPoint結(jié)束坐標,options開始坐標之前or開始之后開始漸變
CGContextDrawLinearGradient(context, gradient,CGPointMake
(220,90) ,CGPointMake(240,110),
kCGGradientDrawsAfterEndLocation);
CGContextRestoreGState(context);// 恢復(fù)到之前的context
//再寫一個看看效果
CGContextSaveGState(context);
CGContextMoveToPoint(context, 260, 90);
CGContextAddLineToPoint(context, 280, 90);
CGContextAddLineToPoint(context, 280, 100);
CGContextAddLineToPoint(context, 260, 100);
CGContextClip(context);//裁剪路徑
//說白了,開始坐標和結(jié)束坐標是控制漸變的方向和形狀
CGContextDrawLinearGradient(context, gradient,CGPointMake
(260, 90) ,CGPointMake(260, 100),
kCGGradientDrawsAfterEndLocation);
CGContextRestoreGState(context);// 恢復(fù)到之前的context
}
-
CGContextStrokeRect()繪制方框,也就是矩形 -
CGContextFillRect繪制一個填充框,默認顏色黑色 -
CGContextSetFillColorWithColor設(shè)置線條填充顏色 -
CGContextSetStrokeColorWithColor設(shè)置邊框顏色 -
CGContextAddRect畫方框(和1,2不一樣) -
CAGradientLayer漸變色填充,其實就是自己寫一個漸變色的layer,添加到視圖上 -
CGContextDrawLinearGradientgradient漸變顏色,startPoint開始漸變的起始位置,endPoint結(jié)束坐標,options開始坐標之前or開始之后開始漸變
大家可以看注釋,注釋寫的很清楚
橢圓
效果圖:

- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
//畫橢圓
CGContextAddEllipseInRect(context, CGRectMake(120, 120, 200, 88)); //橢圓
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);//填充顏色
CGContextDrawPath(context, kCGPathFillStroke);
}
曲線
二階曲線,三階曲線
效果圖如下:

- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
/*畫貝塞爾曲線*/
//二次曲線
CGContextMoveToPoint(context, 120, 300);//設(shè)置Path的起點
CGContextAddQuadCurveToPoint(context,190, 310, 120, 390);//設(shè)置貝塞爾曲線的控制點坐標和終點坐標
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);//線框顏色
CGContextSetLineWidth(context, 3.0);//線的寬度
CGContextStrokePath(context);
//三次曲線函數(shù)
CGContextMoveToPoint(context, 200, 300);//設(shè)置Path的起點
CGContextAddCurveToPoint(context,250, 280, 250, 400, 280, 300);//設(shè)置貝塞爾曲線的控制點坐標和控制點坐標終點坐標
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);//線框顏色
CGContextSetLineWidth(context, 3.0);//線的寬度
CGContextStrokePath(context);
}
圖像繪制
我們可以將一張已有的icon,渲染到畫布中:

- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
UIImage *image = [UIImage imageNamed:@"buttonS"];
[image drawInRect:CGRectMake(60, 340, 20, 20)];//在坐標中畫出圖片
// [image drawAtPoint:CGPointMake(100, 340)];//保持圖片大小在point點開始畫圖片,可以把注釋去掉看看
CGContextDrawImage(context, CGRectMake(100, 340, 20, 20), image.CGImage);//使用這個使圖片上下顛倒,鏡像.參考http://blog.csdn.net/koupoo/article/details/8670024
}
CGContextDrawImage可以讓圖片鏡像,上下顛倒。
給圖像繪制文字
這個特殊需求
這個不屬于本篇文章的介紹內(nèi)容。
算是課后作業(yè)吧!大家運行一下看看結(jié)果吧!
不知道有人了解 Quart2D繪圖嗎???
+ (UIImage *)drawText1:(NSString *)text1 forImage:(UIImage *)image{
CGSize size = CGSizeMake(image.size.width,image.size.height ); // 畫布大小
UIGraphicsBeginImageContextWithOptions(size,NO,0.0);
[image drawAtPoint:CGPointMake(0,0)];
// 獲得一個位圖圖形上下文
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawPath(context,kCGPathStroke);
NSDictionary *attributes = @{ NSFontAttributeName:[UIFont systemFontOfSize:10], NSForegroundColorAttributeName:[UIColor redColor]};
// 畫文字 讓文字處于居中模式
[text1 drawAtPoint:CGPointMake(3,2) withAttributes:attributes];
// 返回繪制的新圖形
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
關(guān)于CGContextRef的使用
這是從網(wǎng)上摘抄過來的,參考一下吧:
0 CGContextRef context = UIGraphicsGetCurrentContext(); 設(shè)置上下文
1 CGContextMoveToPoint 開始畫線
2 CGContextAddLineToPoint 畫直線
4 CGContextAddEllipseInRect 畫一橢圓
4 CGContextSetLineCap 設(shè)置線條終點形狀
4 CGContextSetLineDash 畫虛線
4 CGContextAddRect 畫一方框
4 CGContextStrokeRect 指定矩形
4 CGContextStrokeRectWithWidth 指定矩形線寬度
4 CGContextStrokeLineSegments 一些直線
5 CGContextAddArc 畫已曲線 前倆店為中心 中間倆店為起始弧度 最后一數(shù)據(jù)為0則順時針畫 1則逆時針
5 CGContextAddArcToPoint(context,0,0, 2, 9, 40);//先畫倆條線從point 到 弟1點 , 從弟1點到弟2點的線 切割里面的圓
6 CGContextSetShadowWithColor 設(shè)置陰影
7 CGContextSetRGBFillColor 這只填充顏色
7 CGContextSetRGBStrokeColor 畫筆顏色設(shè)置
7 CGContextSetFillColorSpace 顏色空間填充
7 CGConextSetStrokeColorSpace 顏色空間畫筆設(shè)置
8 CGContextFillRect 補充當(dāng)前填充顏色的rect
8 CGContextSetAlaha 透明度
9 CGContextTranslateCTM 改變畫布位置
10 CGContextSetLineWidth 設(shè)置線的寬度
11 CGContextAddRects 畫多個線
12 CGContextAddQuadCurveToPoint 畫曲線
13 CGContextStrokePath 開始繪制圖片
13 CGContextDrawPath 設(shè)置繪制模式
14 CGContextClosePath 封閉當(dāng)前線路
15 CGContextTranslateCTM(context, 0, rect.size.height); CGContextScaleCTM(context, 1.0, -1.0);反轉(zhuǎn)畫布
16 CGContextSetInterpolationQuality 背景內(nèi)置顏色質(zhì)量等級
16 CGImageCreateWithImageInRect 從原圖片中取小圖
17 字符串的 寫入可用 nsstring本身的畫圖方法 - (CGSize)drawInRect:(CGRect)rect withFont:(UIFont )font lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment;來寫進去即可
18對圖片放大縮小的功能就是慢了點 UIGraphicsBeginImageContext(newSize); UIImage newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
19 CGColorGetComponents() 返回顏色的各個直 以及透明度 可用只讀const float 來接收 是個數(shù)組
結(jié)語:
本文代碼參考了IOS用CGContextRef畫圖)