###Quartz 2D:
- Quartz 2D是一個二維繪圖引擎,同時支援iOS和Mac OS X系統(跨平臺,純C語言)。包含在Core Graphics框架中。
Quartz 2D能完成的工作:
- 繪製圖形: 線條/三角形/矩形/圓/弧等
- 繪製文字
- 繪製/生成圖片
- 讀取/生成PDF
- 自定義UI控制元件
- ... ...
Quartz 2D繪圖主要步驟:
-
通過Quartz 2D原生API繪圖:
- 獲取[圖形上下文]物件
- 向[圖形上下文]物件中新增[路勁]
- 渲染(把[圖形上下文]中的圖形繪製到對應的裝置上)
圖形上下文CGContextRef
- 圖形上下文(Graphics Context): 是一個CGContextRef型別的資料
- 圖形上下文中主要包含如下資訊:
- 繪製路徑(各種各樣的圖形)
- 繪圖狀態(顏色、線寬、樣式、旋轉、縮放、平移、圖片剪裁區域等)
- 輸出目標(繪製到什麼地方去?UIView、PDF、印表機等)
圖形上下文:
提供了以下幾種圖形上下文:
- Bitmap Graphics Context --效果畫到圖片上
- PDF Graphics Context --畫到PDF上
- Window Graphics Context --畫到Mac電腦視窗上
- Layer Graphics Context(UI 控制元件) --畫到UI控制元件上
- Printer Graphics Context --畫到印表機
PS: 相同的一套繪圖序列,指定不同的Graphics Context, 就可以將相同的影像繪製到不同的目標上。
通過UIBezierPath + 圖形上下文繪製圖形:
- 獲取圖形上下文物件
- 建立UIBezierPath物件
- 向UIBezierPath物件中繪製圖形
- 把UIBezierPath物件新增到上下文中
- 把上下文物件渲染到裝置上
PS: UIBezierPath物件可以獨立使用,無需手動獲取 圖形上下文 物件,這裡為了更好的理解 圖形上下文物件,採取手動獲取圖形上下文物件的方式來繪圖。
自定義UIView時,實現檔案中:
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
複製程式碼
__即:__在drawRect:方法中才能取得跟view相關聯的圖形上下文 我們才能繪製各種圖形。
drawRect: 方法僅在view第一次顯示在Window上時呼叫一次,如果想重新呼叫 需要手動呼叫setNeedsDisplay或setNeedsDisplayInRect:方法。
不可手動呼叫drawRect: 方法,該方法是由系統在需要呼叫的時候呼叫--不能主動呼叫該方法。
-
Quartz 2D原生API繪製:
- 繪製直線:
//1.獲取圖形上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//2. 繪製各種路徑
//2.1 設定一個起點
CGContextMoveToPoint(ref, 20, 100);
//2.2 設定一個終點
CGContextAddLineToPoint(ref, 100, 160);
//3. 渲染
CGContextStrokePath(ref);
複製程式碼
- 繪製三角形:
//1.獲取圖形上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//2. 繪製各種路徑
//2.1 設定一個起點
CGContextMoveToPoint(ref, 20, 100);
//2.2 設定一個終點
CGContextAddLineToPoint(ref, 100, 160);
//2.3 再新增一個終點
CGContextAddLineToPoint(ref, 150, 100);
//2.4 關閉路徑
CGContextClosePath(ref);
//3. 渲染
CGContextStrokePath(ref);
複製程式碼
- UIBezierPath繪製圖形:
- 繪製直線:
//1. 獲取圖形上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//2. 建立UIBezierPath物件
UIBezierPath *path = [UIBezierPath bezierPath];
//3. 向UIBezierPath新增路徑
[path moveToPoint:CGPointMake(30, 100)];
[path addLineToPoint:CGPointMake(300, 300)];
//4. 把UIBezierPath物件新增到上下文中
CGContextAddPath(ref, path.CGPath);
//設定狀態資訊
//i. 線寬
CGContextSetLineWidth(ref, 10);
//ii. 設定線段兩端樣式
/*
typedef CF_ENUM(int32_t, CGLineCap) {
kCGLineCapButt, //預設
kCGLineCapRound,
kCGLineCapSquare
};
*/
CGContextSetLineCap(ref, kCGLineCapRound);
//iii. 設定線段連線處的樣式
/*
typedef CF_ENUM(int32_t, CGLineJoin) {
kCGLineJoinMiter, //預設
kCGLineJoinRound,
kCGLineJoinBevel
};
*/
CGContextSetLineJoin(ref, kCGLineJoinRound);
//iV. 設定繪圖顏色
// [[UIColor redColor] setStroke]; //畫邊的時候使用紅色 --僅用於渲染時 為kCGPathStroke時
// [[UIColor yellowColor] setFill]; //設定填充時顏色 --kCGPathFill
[[UIColor blueColor] set]; //填充和描邊 使用同一顏色
//5. 渲染
// CGContextStrokePath(ref);
//上面所有的設定狀態的程式碼,都會將狀態應用於當前上下文中的所有路徑
// CGContextDrawPath(ref, kCGPathStroke); //與[[UIColor redColor] setStroke];對應
// CGContextDrawPath(ref, kCGPathFill); //與[[UIColor yellowColor] setFill];對應
CGContextDrawPath(ref, kCGPathFillStroke); //既填充也描邊 //與[[UIColor blueColor] set];對應
複製程式碼
- 繪製三角形:
//1. 獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//2. 建立UIBezierPath物件
UIBezierPath *path = [UIBezierPath bezierPath];
//3. 向UIBezierPath新增路徑
[path moveToPoint:CGPointMake(100, 200)];
[path addLineToPoint:CGPointMake(160, 300)];
[path addLineToPoint:CGPointMake(220, 200)];
//關閉路徑
[path closePath];
//4. 把UIBezierPath物件新增到上下文中
CGContextAddPath(ref, path.CGPath); //OC物件 轉 C語言
//5. 渲染
// CGContextStrokePath(ref);
//or
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
複製程式碼
- 繪製矩形:
//獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//建立UIBezierPath
//向UIBezierPath中新增路徑
//繪製矩形
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 200, 100)];
//把UIBezierPath新增到上下文中
CGContextAddPath(ref, path.CGPath);
//渲染
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
// CGContextDrawPath(ref, kCGPathFill); //填充
複製程式碼
- 繪製橢圓:
//獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//建立UIBezierPath
//向UIBezierPath中新增路徑
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 200, 100)];
//把UIBezierPath新增到上下文中
CGContextAddPath(ref, path.CGPath);
//渲染
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
// CGContextDrawPath(ref, kCGPathFill); //填充
複製程式碼
-
繪製圓形:
- 第一種方式: 畫橢圓方法 --寬高相等
//獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//建立UIBezierPath
//向UIBezierPath中新增路徑
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 100, 100)];
//把UIBezierPath新增到上下文中
CGContextAddPath(ref, path.CGPath);
//渲染
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
// CGContextDrawPath(ref, kCGPathFill); //填充
複製程式碼
- 第二種方式: 繪製矩形 --寬高相等 cornerRadius: 邊長/2.0
複製程式碼
//獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//建立UIBezierPath
//向UIBezierPath中新增路徑
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 100, 100) cornerRadius:50];
//把UIBezierPath新增到上下文中
CGContextAddPath(ref, path.CGPath);
//渲染
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
// CGContextDrawPath(ref, kCGPathFill); //填充
複製程式碼
- 第三種方式: 繪製圓弧方式畫一個圓
複製程式碼
//獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//建立UIBezierPath
//向UIBezierPath中新增路徑
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
//把UIBezierPath新增到上下文中
CGContextAddPath(ref, path.CGPath);
//渲染
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
// CGContextDrawPath(ref, kCGPathFill); //填充
複製程式碼
- 繪製圓弧:
//獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//建立UIBezierPath
//向UIBezierPath中新增路徑
//畫弧
//ArcCenter: 圓心
//radius: 半徑
//startAngle: 開始弧度 --1弧度 = 180度
//endAngle: 結束弧度
//繪製一個弧 clockwise: 順時針或逆時針
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:50 startAngle:0 endAngle:M_PI_2 clockwise:NO];
//把UIBezierPath新增到上下文中
CGContextAddPath(ref, path.CGPath);
//渲染
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
// CGContextDrawPath(ref, kCGPathFill); //填充
複製程式碼
- 繪製圓環:
//獲取上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//建立UIBezierPath
//向UIBezierPath中新增路徑
//畫圓環
//直接畫一個圓 設定線寬 --推薦使用這種方式
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:50 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
CGContextSetLineWidth(ref, 20); //線寬 裡外各一半
//把UIBezierPath新增到上下文中
CGContextAddPath(ref, path.CGPath);
//渲染
/*
typedef CF_ENUM (int32_t, CGPathDrawingMode) {
kCGPathFill,
kCGPathEOFill,
kCGPathStroke,
kCGPathFillStroke,
kCGPathEOFillStroke
};
*/
CGContextDrawPath(ref, kCGPathStroke);
// CGContextDrawPath(ref, kCGPathFill); //填充
複製程式碼
參考資料: 傳智播客教程 iOS-Quartz2D