Quartz2D的API是純C語言的
Quartz2D的API來自于Core Graphics框架
數據類型和函數基本都以CG作為前綴
在drawRect:方法中取得上下文后,就可以繪制東西到view上
View內部有個layer(圖層)屬性,drawRect:方法中取得的是一個Layer Graphics Context,因此,繪制的東西其實是繪制到view的layer上去了
View之所以能顯示東西,完全是因為它內部的layer
1.獲得圖形上下文CGContextRef ctx = UIGraphicsGetCurrentContext();2.拼接路徑(下面代碼是搞一條線段)CGContextMoveToPoint(ctx, 10, 10);CGContextAddLineToPoint(ctx, 100, 100);3.繪制路徑CGContextStrokePath(ctx); // CGContextFillPath(ctx);新建一個起點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)drawRect:(CGRect)rect { // 獲得上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(50, 150)]; [path addLineToPoint:CGPointMake(250, 150)]; // 保存一個狀態 CGContextSaveGState(ref); CGContextSetLineWidth(ref, 20); [[UIColor redColor] set]; CGContextAddPath(ref, path.CGPath); CGContextStrokePath(ref); path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(150, 50)]; [path addLineToPoint:CGPointMake(150, 250)]; // 還原狀態 CGContextRestoreGState(ref); CGContextAddPath(ref, path.CGPath); CGContextStrokePath(ref);}void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)旋轉void CGContextRotateCTM(CGContextRef c, CGFloat angle)平移void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)// CG:core graphics- (void)drawRect:(CGRect)rect { // 1.獲得上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); // 2.描述路徑 UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 100)]; // 平移 CGContextTranslateCTM(ref, 100, 100); // 旋轉 CGContextRotateCTM(ref, M_PI_4); // 縮放 CGContextScaleCTM(ref, 0.5, 0.5); // 3.添加路徑到上下文 CGContextAddPath(ref, path.CGPath); // 4.渲染路徑 CGContextFillPath(ref);}使用含有“Create”或“Copy”的函數創建的對象,使用完后必須釋放,否則將導致內存泄露
使用不含有“Create”或“Copy”的函數獲取的對象,則不需要釋放
如果retain了一個對象,不再使用時,需要將其release掉
可以使用Quartz 2D的函數來指定retain和release一個對象。例如,如果創建了一個CGColorSpace對象,則使用函數CGColorSpaceRetain和CGColorSpaceRelease來retain和release對象。
也可以使用Core Foundation的CFRetain和CFRelease。注意不能傳遞NULL值給這些函數
/** 原始方法畫直線三 */- (void)drawThree{ // 1. 圖形上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); // 2.描述路徑 CGContextMoveToPoint(ref, 50, 50); CGContextAddLineToPoint(ref, 100, 200); // 3. 渲染 CGContextStrokePath(ref);}/** 原始方法畫直線er */- (void)drawLineTwo{ // 1. 圖形上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); // 2. 描述路徑 CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path, NULL, 50, 50); CGPathAddLineToPoint(path, NULL, 200, 250); // 默認第二條線以第一條線的終點為起點 CGPathAddLineToPoint(path, NULL, 30, 200); // 3. 添加路徑到圖形上下文 CGContextAddPath(ref, path); // 4. 渲染上下文 CGContextStrokePath(ref);}/** 原始方法畫直線一 */- (void)drawLineOne{ // 1.拿到圖形上下文 CGContextRef ref = UIGraphicsGetCurrentContext(); // 2.描述路徑 CGMutablePathRef path = CGPathCreateMutable(); // 添加起點 CGPathMoveToPoint(path, NULL, 50, 50); // 添加一條線到終點 CGPathAddLineToPoint(path, NULL, 200, 200); // 設置顏色 [[UIColor redColor] set]; // 3.添加路徑到上下文 CGContextAddPath(ref, path); // 4.渲染上下文 CGContextStrokePath(ref);}/** 貝塞爾曲線畫直線 */- (void)besizer{ // UIKit提供的 UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(50, 50)]; [path addLineToPoint:CGPointMake(100, 200)]; [[UIColor greenColor] set]; [path stroke];}/** 畫曲線,只能用原始方法 */- (void)drawQuadratic{ CGContextRef ref = UIGraphicsGetCurrentContext(); CGContextMoveToPoint(ref, 50, 50); /* Append a quadratic curve from the current point to `(x, y)', with control point `(cpx, cpy)'. */ // (150,20)是控制點,控制曲線 // (100, 150)是曲線終點 CGContextAddQuadCurveToPoint(ref, 150, 20, 100, 150); CGContextStrokePath(ref);}/** 貝塞爾畫扇形 */- (void)bezierArc{ CGFloat radius = self.bounds.size.width * 0.5; // 貝塞爾畫圓的時候,起點startAngle是三點鐘方向,clockwise是yes表示順時針,反之表示逆時針。 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius-2 startAngle:0 endAngle:M_PI_2 clockwise:YES]; [path addLineToPoint:CGPointMake(radius, radius)]; [path fill];}/** 什么時候調用: 控制器的view即將顯示的時候調用 *//** viewDidLoad->viewWillAppear->drawRect->viewDidAppear*//** drawRect不能手動調用,因為圖形上下文我們自己創建不了,自能由系統創建 */- (void)drawRect:(CGRect)rect { CGFloat radius = MIN(self.bounds.size.width, self.bounds.size.height) * 0.5; CGFloat endAngle = self.slider * M_PI * 2 - M_PI_2; UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius-2 startAngle:-M_PI_2 endAngle:endAngle clockwise:YES]; [path stroke];}- (void)setSlider:(CGFloat)slider{ _slider = slider; // 重繪 [self setNeedsDisplay];}- (void)drawRect:(CGRect)rect { NSArray *arrData = [NSArray randomArray]; CGFloat radius = self.bounds.size.width * 0.5; CGPoint center = CGPointMake(radius, radius); UIBezierPath *path = nil; CGFloat startAngle = 0; CGFloat endAngle = 0; for (int i = 0; i<arrData.count; i++) { // 起點角度等于上一個的終點角度 startAngle = endAngle; // 終點角度等于起點角度+自身的弧度 endAngle = startAngle + ([arrData[i] floatValue]/100)*M_PI*2; path = [UIBezierPath bezierPathWithArcCenter:center radius:radius-2 startAngle:startAngle endAngle:endAngle clockwise:YES]; [path addLineToPoint:center]; [[UIColor colorWithRandom] set]; [path fill]; }}- (NSArray *)randomArr{ // +1 避免隨機出來的是0 int count = arc4random_uniform(10) + 1; int max = 100; int random = 0; NSMutableArray *arrData = [NSMutableArray array]; for(int i = 0; i<count; i++) { // 避免隨機出來的是0 random = arc4random_uniform(max) + 1; [arrData addObject:@(random)]; if (random == max) { break; } max -= random; } if (max) { [arrData addObject:@(max)]; } return arrData;}/** 點擊的時候,就重繪一次 */- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self setNeedsDisplay];}- (void)drawRect:(CGRect)rect{ NSArray *arrData = [NSArray randomArray]; // 總個數(包括間距+柱狀圖) NSInteger postCount = 2 * arrData.count - 1; // 寬度 CGFloat postW = self.bounds.size.width / postCount; UIBezierPath *path = nil; CGFloat x = 0; CGFloat y = 0; CGFloat h = 0; for (int i = 0; i < arrData.count; i++) { x = i * 2 * postW; h = ([arrData[i] floatValue] / 100) * self.bounds.size.height; y = self.bounds.size.height - h; path = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, postW, h)]; [[UIColor randomColor] set]; [path fill]; }}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self setNeedsDisplay];}// 默認情況下:// [str drawAtPoint:CGPointMake(0, 0) withAttributes:dict]; 不會換行// [str drawInRect:rect withAttributes:dict]; 會自動換行// [image drawAtPoint:CGPointMake(0, 0)];默認繪制的圖片和圖片大小一樣// [image drawInRect:rect];會把圖片大小索縮放成跟rect大小一樣// [image drawaspatternInRect:self.bounds]; 會自動進行平鋪//- (void)drawRect:(CGRect)rect{ UIImage *image = [UIImage imageNamed:@"001"]; // 可以進行裁剪,但是必須放在繪制之前 UIRectClip(CGRectMake(0, 0, 50, 50)); [image drawAsPatternInRect:self.bounds];}- (void)drawStr{ NSString *str = @"Say_Alin,文能提筆控蘿莉,武能編碼調bug"; NSDictionary *dict = @{NSFontAttributeName:[UIFont systemFontOfSize:40], NSForegroundColorAttributeName:[UIColor redColor], NSStrokeWidthAttributeName:@10}; // [str drawAtPoint:CGPointMake(0, 0) withAttributes:dict]; [str drawInRect:self.bounds withAttributes:dict];}- (void)drawImage{ UIImage *image = [UIImage imageNamed:@"黃人"]; // [image drawAtPoint:CGPointMake(0, 0)]; [image drawInRect:self.bounds];}新聞熱點
疑難解答