Quartz2D,quartz
一、Quartz2D概述
Quartz2D是一個二維繪圖引擎,同時支援Mac和iOS系統
Quartz2D能繪製圖形、繪製文字、繪製圖片、產生PDF、裁剪圖片等,還可以用來自訂UI控制項。
例如畫板應用、手勢解鎖功能、圖形報表等都是用Quartz2D實現的。
1. 圖形上下文(Graphics Context)
圖形上下文(Graphics Context)是一個CGContextRef類型的資料,它用來儲存繪圖資訊、繪圖狀態和決定繪製的輸出目標(輸出目標可以是PDF檔案、Bitmap或者顯示器的視窗上)。
相同的一套繪圖序列,指定不同的圖形上下文可將相同的映像繪製到不同的目標上。
Quartz2D提供了一下幾種類型的Graphics Context:
- Bitmap Graphics Context
- PDF Graphics Context
- Window Graphics Context
- Layer Graphics Context
- Printer Graphics Context
2. drawRect:方法
當view第一次顯示到螢幕上時(被加到UIWindow上顯示出來)就會調用drawRect:,調用view的setNeedDisplay或者setNeedDisplayInRect:時也會調用drawRect:
3. drawRect:中取得上下文
在drawRect:方法中取得上下文後,就可以繪製圖形到view上面了。view內部有個layer屬性,drawRect:方法中取得的是一個Layer Graphics Context,因此繪製的圖形其實是繪製到view的layer上去了。
view之所以能顯示東西,是因為它內部有layer。
4. Quartz2D的記憶體管理
使用含有“Create”或“Copy”的函數建立的對象,使用完後必須釋放,否則將導致記憶體泄露,使用不含“Create”或“Copy”的函數擷取的對象,則不需要釋放。
如果retain了一個對象,不再使用時也需要將其release掉。
可以使用Quartz2D的函數來指定retain和release一個對象,例如,如果建立了一個CGColorSpace對象,則使用函數CGColorSpaceRetain和CGColorSpaceRelease來retain和release對象。
也可以使用Core Foundation的CFRetain和CFRelease。注意不能傳遞NULL值給這些函數。
二、代碼1. 畫三角形
1 /** 2 * 畫三角形 3 */ 4 void drawTriangle() 5 { 6 // 1.獲得圖形上下文 7 CGContextRef contextRef = UIGraphicsGetCurrentContext(); 8 9 // 2.拼接圖形路徑10 // 設定一個起點11 CGContextMoveToPoint(contextRef, 100, 100);12 // 添加一條線段到(100,100)13 CGContextAddLineToPoint(contextRef, 200, 200);14 // 添加一條線段到(150,40)15 CGContextAddLineToPoint(contextRef, 150, 40);16 // 關閉路徑(串連起點和終點)17 CGContextClosePath(contextRef);18 19 // 3.渲染顯示到View上面20 CGContextStrokePath(contextRef);21 }
2. 畫矩形
1 /** 2 * 畫四邊形 3 */ 4 void drawQuadrilateral() 5 { 6 // 1.獲得圖形上下文 7 CGContextRef contextRef = UIGraphicsGetCurrentContext(); 8 // 2.畫矩形 9 CGContextAddRect(contextRef, CGRectMake(100, 100, 150, 100));10 // 3.繪製圖形11 CGContextStrokePath(contextRef);12 }
3. 畫圓
1 /** 2 * 畫圓 3 */ 4 void drawCircle() 5 { 6 // 1.獲得圖形上下文 7 CGContextRef contextRef = UIGraphicsGetCurrentContext(); 8 // 2.畫圓 9 CGContextAddEllipseInRect(contextRef, CGRectMake(100, 100, 100, 100));10 // 3.繪製圖形11 CGContextFillPath(contextRef);12 }
4. 畫圓弧
1 /** 2 * 畫圓弧 3 */ 4 void drawArc() 5 { 6 // 1.獲得圖形上下文 7 CGContextRef contextRef = UIGraphicsGetCurrentContext(); 8 9 // 2.畫圓弧10 // x\y : 圓心座標11 // radius : 半徑12 // startAngle : 開始角度13 // endAngle : 結束角度14 // clockwise : 圓弧的伸展方向(0:順時針, 1:逆時針)15 CGContextAddArc(contextRef, 100, 100, 50, 0, M_PI, 1);16 17 // 3.繪製圖形18 CGContextStrokePath(contextRef);19 }
5. 畫文字
1 /** 2 * 畫文字 3 */ 4 void drawText() 5 { 6 NSString *str = @"畫文字"; 7 // 設定文字屬性 8 NSMutableDictionary *attrs = [NSMutableDictionary dictionary]; 9 attrs[NSForegroundColorAttributeName] = [UIColor redColor];10 attrs[NSFontAttributeName] = [UIFont systemFontOfSize:20];11 12 // 將文字畫在某個位置13 [str drawAtPoint:CGPointMake(100, 100) withAttributes:attrs];14 15 // 將文字畫在矩形框內16 // [str drawInRect:CGRectMake(100, 100, 100, 100) withAttributes:attrs];17 }
6. 畫圖片
1 /**2 * 畫圖片3 */4 void drawImage()5 {6 UIImage *image = [UIImage imageNamed:@"1.jpg"];7 [image drawAsPatternInRect:CGRectMake(100, 100, 100, 100)];8 }
7. 圖形上下文棧
1 /** 2 * 圖形上下文棧 3 */ 4 void ContextSaveGState() 5 { 6 // 獲得圖形上下文 7 CGContextRef contextRef = UIGraphicsGetCurrentContext(); 8 9 // 將contextRef拷貝一份放到棧中10 CGContextSaveGState(contextRef);11 12 // 設定繪圖狀態13 CGContextSetLineWidth(contextRef, 10);14 [[UIColor redColor] set];15 CGContextSetLineCap(contextRef, kCGLineCapRound);16 17 // 第一根線18 CGContextMoveToPoint(contextRef, 50, 50);19 CGContextAddLineToPoint(contextRef, 120, 190);20 21 // 畫線22 CGContextStrokePath(contextRef);23 24 // 將棧頂的上下文出棧,替換當前的上下文25 CGContextRestoreGState(contextRef);26 27 // 第二根線28 CGContextMoveToPoint(contextRef, 10, 70);29 CGContextAddLineToPoint(contextRef, 220, 290);30 31 // 畫線32 CGContextStrokePath(contextRef);33 }
8. 矩陣操作(圖形整體縮放、移動、旋轉等等)
1 /** 2 * 矩陣操作 3 */ 4 void contextMatrix() 5 { 6 // 獲得圖形上下文 7 CGContextRef contextRef = UIGraphicsGetCurrentContext(); 8 9 // 縮小0.5倍(在畫線條之前設定)10 CGContextScaleCTM(contextRef, 0.5, 0.5);11 // 旋轉12 CGContextRotateCTM(contextRef, M_PI_4);13 // 移動14 CGContextTranslateCTM(contextRef, 0, 150);15 16 // 畫矩形17 CGContextAddRect(contextRef, CGRectMake(100, 100, 100, 100));18 CGContextStrokePath(contextRef);19 }
9. 圖片裁剪
1 /** 2 * 圖片裁剪 3 */ 4 - (void)imageClip 5 { 6 // 1.載入原圖 7 UIImage *oldImage = [UIImage imageNamed:@"1.jpg"]; 8 // 2.開啟上下文 9 UIGraphicsBeginImageContextWithOptions(oldImage.size, NO, 0.0);10 // 3.取得當前的上下文11 CGContextRef contextRef = UIGraphicsGetCurrentContext();12 // 4.畫圓13 CGRect circleRect = CGRectMake(0, 0, oldImage.size.width, oldImage.size.height);14 CGContextAddEllipseInRect(contextRef, circleRect);15 // 5.按照當前的路徑形狀(圓形)裁剪,超出這個形狀以外的內容都不顯示16 CGContextClip(contextRef);17 // 6.畫圖18 [oldImage drawInRect:circleRect];19 // 7.取圖20 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();21 // 8.結束22 UIGraphicsEndImageContext();23 }
10. 截屏
1 /** 2 * 截屏 3 */ 4 - (void)screenCut 5 { 6 // 1.開啟上下文 7 UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0); 8 // 2.將控制器view的layer渲染到上下文 9 [self.layer renderInContext:UIGraphicsGetCurrentContext()];10 // 3.取出圖片11 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();12 // 4.結束上下文13 UIGraphicsEndImageContext();14 }
11. 重繪
1 /**2 * 重繪3 */4 - (void)reDraw5 {6 // 重繪(這個方法內部會重新調用drawRect:方法進行繪製)7 [self setNeedsDisplay];8 }
12. 常用屬性
1 /** 2 * 常用屬性 3 */ 4 void ContextProperty() 5 { 6 // 獲得圖形上下文 7 CGContextRef contextRef = UIGraphicsGetCurrentContext(); 8 9 // 設定線段寬度10 CGContextSetLineWidth(contextRef, 10);11 // 設定顏色12 CGContextSetRGBStrokeColor(contextRef, 1, 0, 0, 1);13 // 設定線段頭尾部樣式14 CGContextSetLineCap(contextRef, kCGLineCapRound);15 // 設定線段轉折點的樣式16 CGContextSetLineJoin(contextRef, kCGLineJoinRound);17 // set : 同時設定為實心和空心顏色18 // setStroke : 設定空心顏色19 // setFill : 設定實心顏色20 [[UIColor whiteColor] set];21 22 // 裁剪,裁剪後所畫內容只能在裁剪的範圍內顯示23 CGContextClip(contextRef);24 }