本篇DEMO
在iOS中進(jìn)行繪圖,不管你是否了解,基本上就是使用的Core Graphics。Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低階別、輕量級、高保真度的2D渲染,該框架可以用于基于路徑的繪圖、變換、顏色管理、脫屏渲染、模板、漸變、遮蔽、圖像數(shù)據(jù)處理、圖像的創(chuàng)建、遮罩、以及PDF文檔的創(chuàng)建、顯示和分析。
Core Graphics API的所有操作都是在一個上下文中進(jìn)行。所以在繪圖之前,我們需要去獲取該上下文,并傳入執(zhí)行渲染的函數(shù)中。
- 獲取上下文的幾種方式
//創(chuàng)建圖片類型的上下文
UIGraphicsBeginImageContextWithOptions
//UIView,在drawRect中,Cocoa會為你創(chuàng)建一個圖形上下文
- (void)drawRect:(CGRect)rect
//CALayer
- (void)drawInContext:(CGContextRef)ctx
//delegate回調(diào)
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
- UIGraphicsBeginImageContextWithOptions函數(shù)創(chuàng)建的上下文適用于圖像操作,并且該上下文屬于當(dāng)前上下文,你也可以通過UIGraphicsGetCurrentContext函數(shù)獲得當(dāng)前圖形上下文
- drawRect方法調(diào)用時,Cocoa創(chuàng)建的上線屬于當(dāng)前圖形上下文,你也可以通過UIGraphicsGetCurrentContext函數(shù)獲得當(dāng)前圖形上下文
- delegate回調(diào)所持有的context,只是對一個圖形上下文的引用,并不一定是當(dāng)前上下文
繪圖框架
UIKit
像UIImage、NSString、UIBezierPath、UIColor都提供了方法幫助我們完成繪圖任務(wù),雖然功能有限,但大多數(shù)情況下都能滿足我們的需求
Core Graphics
這是一個繪圖專用的API族,通常也被成為QuartZ 2D。Core Graphics是iOS上所有繪圖功能的基石,包括UIKit。
下面我們通過栗子來介紹幾種不同的繪圖方法
UIKit:在UIView的子類方法drawRect方法中進(jìn)行繪圖
- (void)drawRect:(CGRect)rect {
//繪制一個空心圓
UIBezierPath *round = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.bounds.size.width/2];
[[UIColor redColor] setStroke];
[round stroke];
}
Core Graphics:在drwaRect中實(shí)現(xiàn)繪制
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// CGMutablePathRef path = CGPathCreateMutable();
// CGPathAddRoundedRect(path, nil, self.bounds, self.bounds.size.width/2, self.bounds.size.width/2);
// CGPathCloseSubpath(path);
// CGContextAddPath(context, path);
CGContextAddEllipseInRect(context, self.bounds);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetLineWidth(context, 10);
// CGContextClip(context);
CGContextStrokePath(context);
}
在代理回調(diào)方法中進(jìn)行繪制
- 需要注意的是設(shè)置CALayer對象的代理時,不要將UIView對象設(shè)置為顯示層的委托對象,這是因?yàn)閁IView對象已經(jīng)是隱式層的代理對象,再將它設(shè)置為兩一個層的委托對象就會出現(xiàn)問題。你可以編寫一個負(fù)責(zé)繪制圖形的代理類。如果你不小心設(shè)置了代理為view,最好在dealloc方法中將layer對象的代理置空。至于繪圖的方法基本就和上邊的類似。
UIGraphicsBeginImageContextWithOptions
- (void)drawRect:(CGRect)rect {
//UIKit
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);
//UIKit
// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.bounds.size.width/2];
// [[UIColor redColor] setStroke];
// [path stroke];
//Core Graphics
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, self.bounds);
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
CGContextSetLineWidth(ctx, 1);
CGContextStrokePath(ctx);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imageV = [[UIImageView alloc] initWithFrame:self.bounds];
[imageV setImage:image];
[self addSubview:imageV];
}
CAShapeLayer繪圖,可以快速實(shí)現(xiàn)一些簡單的動畫
- (void)drawRect:(CGRect)rect {
CAShapeLayer *layer = [CAShapeLayer layer];
layer.strokeColor = [UIColor redColor].CGColor;
layer.fillColor = [UIColor clearColor].CGColor;
layer.lineWidth = 2;
layer.lineCap = kCALineCapRound;
[self.layer addSublayer:layer];
//UIKit
// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.bounds.size.width/2];
// layer.path = path.CGPath;
//Core Graphics
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRoundedRect(path, nil, self.bounds, self.bounds.size.width/2, self.bounds.size.height/2);
CGPathCloseSubpath(path);
layer.path = path;
CGPathRelease(path);
}
- 這些只是繪圖的一些簡單使用,后續(xù)會結(jié)合demo實(shí)現(xiàn)一些復(fù)雜的繪圖。