Quartz 2D是一個二維繪圖引擎,同時支持iOS和Mac系統
Quartz 2D能完成的工作
繪制圖形 : 線條三角形矩形圓弧等
繪制文字
繪制生成圖片(圖像)
讀取生成PDF
截圖裁剪圖片
自定義UI控件
…
為了便於搭建美觀的UI界面,iOS提供了UIKit框架,裡面有各種各樣的UI控件 UILabel:顯示文字 UIImageView:顯示圖片UIButton:同時顯示圖片和文字(能點擊)
… …利用UIKit框架提供的控件,拼拼湊湊,能搭建和現實一些簡單、常見的UI界面
但是,有些UI界面極其復雜、而且比較個性化,用普通的UI控件無法實現,這時可以利用Quartz2D技術將控件內部的結構畫出來,自定義控件的樣子 其實,iOS中大部分控件的內容都是通過Quartz2D畫出來的,因此,Quartz2D在iOS開發中很重要的一個價值是:自定義view(自定義UI控件)
注意點:畫線條只能通過空心樣式畫。
CGContextStrokePath(ctx);
-(void)drawLine
{
//1.獲得圖形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.拼接圖形(路徑)
//畫一條直線
//設置起始位置
CGContextMoveToPoint(ctx, 10, 10);
//添加一條線段到點(100,100)
CGContextAddLineToPoint(ctx, 100, 100);
//設置直線的寬度(黃色)
//CGContextSetRGBStrokeColor(ctx, 0, 1, 0, 1);
//set : 同時設置為空心和實心顏色
//stroke : 設置空心顏色
//fill : 設置失心顏色
[[UIColor yellowColor]set];
//設置直線的寬度
CGContextSetLineWidth(ctx, 10);
//設置直線開頭的樣式(圓)
CGContextSetLineCap(ctx, kCGLineCapRound);
//設置直線轉折點的樣式(圓)
CGContextSetLineJoin(ctx, kCGLineJoinRound);
//3.渲染顯示到View上面
CGContextStrokePath(ctx);
}
-(void)drawTriangle
{
//1.獲得圖形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.拼接圖形(路徑)
//畫一個三角形
//設置起始位置
CGContextMoveToPoint(ctx, 0, 0);
//添加一條線段到點(100,100)
CGContextAddLineToPoint(ctx, 100, 100);
CGContextAddLineToPoint(ctx, 120, 20);
CGContextClosePath(ctx);
//設置直線的寬度(紅色)
[[UIColor redColor]set];
//設置直線的寬度
CGContextSetLineWidth(ctx, 10);
//設置直線轉折點的樣式(切面)
CGContextSetLineJoin(ctx, kCGLineJoinBevel);
//3.渲染顯示到View上面
CGContextStrokePath(ctx);
}
* 方式一
// 1.獲取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.繪制四條線條
CGContextMoveToPoint(ctx, 10, 10);
CGContextAddLineToPoint(ctx, 100, 10);
CGContextAddLineToPoint(ctx, 100, 100);
CGContextAddLineToPoint(ctx, 10, 100);
CGContextClosePath(ctx);
//3.渲染
CGContextStrokePath(ctx);
*方式二
// 1.獲取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.繪制
CGContextAddRect(ctx, CGRectMake(10, 10, 100, 100));
//3.渲染
CGContextStrokePath(ctx);
* 方式三
// 1.獲取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.繪制並渲染
CGContextStrokeRect(ctx, CGRectMake(10, 10, 100, 100));
* 方式四
// 1.獲取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.創建路徑
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path,NULL, CGRectMake(10, 10, 100, 100));
// 3.添加路徑到上下文
CGContextAddPath(ctx, path);
CGPathRelease(path);
// 4.渲染
CGContextStrokePath(ctx);
* 方式五
UIBezierPath *path = [UIBezierPathbezierPathWithRect:CGRectMake(10, 10, 100, 100)];
[path stroke];
void CGContextAddArc (
CGContextRef c,
CGFloat x, //圓心的x坐標
CGFloat y, //圓心的x坐標
CGFloat radius, //圓的半徑
CGFloat startAngle, //開始弧度
CGFloat endAngle, //結束弧度
int clockwise //0表示順時針,1表示逆時針
);
-(void)drawCircle
{
//1.獲得圖形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.拼接圖形
//畫圓
CGContextAddEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));
//設置寬度
CGContextSetLineWidth(ctx, 10);
//設置顏色
[[UIColor purpleColor]set];
//3.渲染到View
CGContextStrokePath(ctx);
}
假如想創建一個完整的圓圈,那麼開始弧度就是0 結束弧度是2pi
最後,函數執行完後,current point就被重置為(x,y).還有一點要注意的是,假如當前path已經存在一個subpath,
那麼這個函數執行的另外一個效果是會有一條直線,從current point到弧的起點。
圖形上下文(Graphics Context):是一個CGContextRef類型的數據
在drawRect:方法中取得上下文後,就可以繪制東西到view上
View內部有個layer(圖層)屬性,drawRect:方法中取得的是一個Layer Graphics Context,因此,繪制的東西其實是繪制到view的layer上去了
View之所以能顯示東西,完全是因為它內部的layer
新建一個起點
void CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)
添加新的線段到某個點
void CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)
添加一個矩形
void CGContextAddRect(CGContextRef c, CGRect rect)
添加一個橢圓
void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)
添加一個圓弧
void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,
CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
Mode參數決定繪制的模式
void CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)
繪制空心路徑
void CGContextStrokePath(CGContextRef c)
繪制實心路徑
void CGContextFillPath(CGContextRef c)
提示:一般以CGContextDraw、CGContextStroke、CGContextFill開頭的函數,都是用來繪制路徑的
將當前的上下文copy一份,保存到棧頂(那個棧叫做”圖形上下文棧”)
void CGContextSaveGState(CGContextRef c)
將棧頂的上下文出棧,替換掉當前的上下文
void CGContextRestoreGState(CGContextRef c)
利用矩陣操作,能讓繪制到上下文中的所有路徑一起發生變化
縮放
void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)
旋轉
void CGContextRotateCTM(CGContextRef c, CGFloat angle)
平移
void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)
使用含有“Create”或“Copy”的函數創建的對象,使用完後必須釋放,否則將導致內存洩露
使用不含有“Create”或“Copy”的函數獲取的對象,則不需要釋放
如果retain了一個對象,不再使用時,需要將其release掉
可以使用Quartz 2D的函數來指定retain和release一個對象。例如,如果創建了一個CGColorSpace對象,則使用函數CGColorSpaceRetain和CGColorSpaceRelease來retain和release對象。
也可以使用Core Foundation的CFRetain和CFRelease。注意不能傳遞NULL值給這些函數
水印的作用
告訴你這個圖片從哪來的
主要是一些網站為了版權問題、廣告而添加的
有時候,在手機客戶端app中也需要用到水印技術
比如,用戶拍完照片後,可以在照片上打個水印,標識這個圖片是屬於哪個用戶的
實現方式:利用Quartz2D,將水印(文字、LOGO)畫到圖片的右下角
#import UIImage+WHJ.h
@implementation UIImage (WHJ)
+(instancetype)waterImageWithBg:(NSString *)bg logo:(NSString * )logo
{
UIImage *bgImage = [UIImage imageNamed:@scene];
//1.創建一個基於位圖的上下文(開啟一個基於位圖的上下文)
//size: 新圖片的尺寸
//opaque : 透明. NO為不透明,YES為透明
//scale : 縮放
//這段代碼過後就相當於創建一個新的bitmap,也就是新的UImage對象
UIGraphicsBeginImageContextWithOptions(bgImage.size, NO, 0.0);
//1.畫背景
[bgImage drawInRect:CGRectMake(0, 0, bgImage.size.width, bgImage.size.height)];
//3.畫右下角的水印
UIImage *waterImage = [UIImage imageNamed:@logo];
CGFloat margin = 5;
CGFloat scale = 0.5;
CGFloat waterW = waterImage.size.width * scale;
CGFloat waterH = waterImage.size.height * scale;
CGFloat waterX = bgImage.size.width - waterW - margin;
CGFloat waterY = bgImage.size.height - waterH -margin;
[waterImage drawInRect:CGRectMake(waterX, waterY, waterW, waterH)];
//4.從上下文取得制作完畢的UIImage對象
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.結束上下文
UIGraphicsEndImageContext();
return newImage;
}
@end
//6.顯示到View
self.iconView.image = newImage;
//7.將image壓縮為PNG格式的二進制數據
NSData * data = UIImagePNGRepresentation(newImage);
//8.寫入文件
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@new.png];
[data writeToFile:path atomically:YES];
// NSLog(@%@,path);
//1.獲得圖片
UIImage *image = [UIImage imageNamed:@abc];
//2.開始圖片上下文
UIGraphicsBeginImageContext(image.size);
//畫圓
//這段代碼獲得的上下文就是上一段代碼開始的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, image.size.width, image.size.height));
CGContextClip(ctx);
//3.繪制圖片
[image drawAtPoint:CGPointZero];
//4.獲得圖片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
self.iconView.image = newImage;
//5.關閉上下文
UIGraphicsEndImageContext();
+(instancetype)catchImageWithView:(UIView *)view
{
//開啟圖形上下文
UIGraphicsBeginImageContext(view.frame.size);
//將控制器中上下文的內容渲染到View中
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
//從圖形上下文獲得圖片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//關閉上下文
UIGraphicsEndImageContext();
return newImage;
}