Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎舶替。它提供了低級(jí)別、輕量級(jí)顾瞪、高保真度的2D渲染。
Core Graphics API所有的操作都在上下文中進(jìn)行栖茉。所以在繪圖之前需要獲取該上下文并傳入執(zhí)行渲染的函數(shù)內(nèi)孵延。
一、 Quartz2D
Quartz2D的API是純C語(yǔ)言的尘应,它是一個(gè)二維繪圖引擎。在iOS開發(fā)中很重要的一個(gè)價(jià)值是:自定義view(自定義UI控件)苍鲜。
使用Quartz2D自定義View
(1)獲取圖形上下文玷犹。圖形上下文相當(dāng)于畫布,是繪畫的地方,會(huì)保存繪圖信息歹颓、繪圖狀態(tài)。
圖形上下文:
//獲取當(dāng)前圖形上下文
1. CGContextRef ctx = UIGraphicsGetCurrentContext();
//創(chuàng)建一個(gè)圖片類型的上下文
2. UIGraphicsBeginImageContextWithOptions
(2)圖形上下文必須與需要自定義的view相關(guān)聯(lián)领跛,才能將內(nèi)容繪制到view上面撤奸。
自定義view的步驟:
- 新建一個(gè)類,繼承自UIView
- 實(shí)現(xiàn)- (void)drawRect:(CGRect)rect方法胧瓜,然后在這個(gè)方法中
a. 取得跟當(dāng)前view相關(guān)聯(lián)的圖形上下文
b .繪制相應(yīng)的圖形內(nèi)容(內(nèi)容就是路徑path)
path的表現(xiàn)形式有多種:
1. CGContextMoveToPoint(需在圖形上下文中操作)
2. UIBezierPath
3. CGMutablePathRef - 利用圖形上下文將繪制的所有內(nèi)容渲染顯示到view上面
Quartz2D的管理原則:
(1)使用含有“Create”或“Copy”的函數(shù)創(chuàng)建的對(duì)象(即retain了一個(gè)對(duì)象)贷痪,使用完后必須釋放(release),否則將導(dǎo)致內(nèi)存泄露
(2)使用不含有“Create”或“Copy”的函數(shù)獲取的對(duì)象劫拢,則不需要釋放
核心方法drawRect:
- 為什么要實(shí)現(xiàn)drawRect:方法才能繪圖到view上?
因?yàn)樵赿rawRect:方法中才能取得跟view相關(guān)聯(lián)的圖形上下文 - drawRect:方法在什么時(shí)候被調(diào)用妹沙?
當(dāng)view第一次顯示到屏幕上時(shí)(被加到UIWindow上顯示出來(lái))
調(diào)用view的setNeedsDisplay或者setNeedsDisplayInRect:時(shí). - 注意4點(diǎn):
- 手動(dòng)調(diào)用drawRect:方法熟吏,不會(huì)自動(dòng)創(chuàng)建跟View相關(guān)聯(lián)的上下文。應(yīng)該 調(diào)用setNeedsDisplay方法,系統(tǒng)底層會(huì)自動(dòng)調(diào)用drawRect牵寺,告訴系統(tǒng)重新繪制View.這樣,系統(tǒng)底層會(huì)自動(dòng)創(chuàng)建跟View相關(guān)聯(lián)的上下文
setNeedsDisplay底層會(huì)調(diào)用drawRect,并不是立馬調(diào)用的.只是設(shè)了一個(gè)調(diào)用的標(biāo)志.調(diào)用時(shí)刻是等下一次屏幕刷新時(shí)才去調(diào)用drawRect趣斤。屏幕每一秒刷新60秒次,所以1秒調(diào)用drawRect方法大概60次,速度非忱栊荩快
view內(nèi)部有個(gè)layer(圖層)屬性,drawRect:方法中取得的是一個(gè)Layer Graphics Context势腮,因此,繪制的東西其實(shí)是繪制到- view的layer上去了
View之所以能顯示東西泪幌,完全是因?yàn)樗鼉?nèi)部的layer
二署照、 繪畫
Quartz2D重要函數(shù)(C函數(shù))
//起點(diǎn)
CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)
//添加線段到某個(gè)點(diǎn)
CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)
//矩形
CGContextAddRect(CGContextRef c, CGRect rect)
//橢圓
CGContextAddEllipseInRect(CGContextRef context, CGRect rect)
//圓弧 (x,y)圓心 radius:半徑 startAngle:起始角度 endAngle:終止角度 clockwise:時(shí)針方向(順時(shí)針/逆時(shí)針)
CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
//繪制空心路徑
CGContextStrokePath(CGContextRef c)
//繪制實(shí)心路徑
CGContextFillPath(CGContextRef c)
//設(shè)置線段寬度
CGContextSetLineWidth(CGContextRef c, CGFloat width)
//設(shè)置線段頭尾部的樣式
CGContextSetLineCap(CGContextRef c, CGLineCap cap)
//設(shè)置線段轉(zhuǎn)折點(diǎn)的樣式
CGContextSetLineJoin(CGContextRef c, CGLineJoin join)
//設(shè)置顏色
1.不常用
CGContextSetRGBStrokeColor(CGContextRef c, CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
CGContextSetRGBFillColor(CGContextRef c, CGFloat red,CGFloat green, CGFloat blue, CGFloat alpha)
2.常用
[[UIColor brownColor] set]
畫圖
- (void)drawRect:(CGRect)rect {
CGFloat rectW = rect.size.width;
CGFloat rectH = rect.size.height;
//取得跟當(dāng)前view相關(guān)聯(lián)的圖形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//繪制相應(yīng)的圖形內(nèi)容
CGContextMoveToPoint(ctx, rectW*.5, 0);
CGContextAddLineToPoint(ctx, 0, rectH*.5);
CGContextAddLineToPoint(ctx, rectW*.3, rectH*.5);
CGContextAddLineToPoint(ctx, rectW*.3, rectH);
CGContextAddLineToPoint(ctx, rectW*.7, rectH);
CGContextAddLineToPoint(ctx, rectW*.7, rectH*.5);
CGContextAddLineToPoint(ctx, rectW, rectH*.5);
CGContextAddLineToPoint(ctx, rectW*.5, 0);
CGContextClosePath(ctx);
CGContextSetLineWidth(ctx, 6);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
[[UIColor blueColor] set];
//利用圖形上下文將繪制的所有內(nèi)容渲染顯示到view上面
CGContextStrokePath(ctx);
}
效果
加水印
- (void)addWaterMarkRect:(CGRect)rect {
UIImageView *imageView = [[UIImageView alloc]init];
imageView.frame = self.bounds;
[self addSubview:imageView];
//1.加載圖片
UIImage *image = [UIImage imageNamed:@"rest"];
//2.創(chuàng)建位圖上下文(size:開啟多大的上下文,就會(huì)生成多大的圖片)
UIGraphicsBeginImageContext(rect.size);
//3.把圖片繪制到上下文當(dāng)中(drawAtPoint:可以多次繪制浴滴,不是重置)
[image drawAtPoint:CGPointZero];
//4.繪制水印
NSString *str = @"ONCE";
NSMutableDictionary *mutableDic = [NSMutableDictionary dictionary];
mutableDic[NSFontAttributeName] = [UIFont boldSystemFontOfSize:20];
mutableDic[NSForegroundColorAttributeName] = [UIColor orangeColor];
NSShadow *shadow = [[NSShadow alloc]init];
shadow.shadowOffset = CGSizeMake(2, 2);
shadow.shadowColor = [UIColor orangeColor];
shadow.shadowBlurRadius = 2;
mutableDic[NSShadowAttributeName] = shadow;
[str drawAtPoint:self.bounds.origin withAttributes:mutableDic];
[str drawAtPoint:CGPointMake(rect.size.width-70, rect.size.height-30) withAttributes:mutableDic];
//5.從上下文當(dāng)中生成一張圖片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//6.關(guān)閉位圖上下文
UIGraphicsEndImageContext();
imageView.image = newImage;
}
效果
注:在上面的繪制水印部分升略,不一定對(duì)文字操作屡限,也可以直接操作UILabel等視圖來(lái)實(shí)現(xiàn)想要的效果
截屏
- (void)Screenshots
{
//生成圖片
//1.開啟一個(gè)位圖上下文
UIGraphicsBeginImageContext(self.view.bounds.size);
//2.把View的內(nèi)容繪制到上下文當(dāng)中
CGContextRef ctx = UIGraphicsGetCurrentContext();
//UIView內(nèi)容想要繪制到上下文當(dāng)中, 必須使用渲染的方式
[self.view.layer renderInContext:ctx];
//3.從上下文當(dāng)中生成一張圖片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//4.關(guān)閉上下文
UIGraphicsEndImageContext();
//把圖片轉(zhuǎn)成二進(jìn)制流
//NSData *data = UIImageJPEGRepresentation(newImage, 1);
NSData *data = UIImagePNGRepresentation(newImage);
[data writeToFile:@"/Users/ONCE/Downloads/ONCE.jpg" atomically:YES];
}
參考資料:
iOS Quartz2D詳解