iOS 繪圖API之Core Graphics系統學習(一)

前言

??iOS支持兩套圖形API族:Core Graphics和OpenGL ES。OpenGL ES是跨平臺的圖形API,屬于OpenGL的一個簡化版本。而QuartZ 2D是蘋果公司開發的一套API,它是Core Graphics Framewore的一部分。
??本文中主要是對Core Graphics框架的學習總結。

??對于一個初學者來說,UIKit和Core Graphics兩個支持繪圖的框架常常令我們感到迷惑。

UIKit

??UIKit是一組Objective-C API,為線條圖形、Quartz圖像和顏色操作提供Objective-C封裝,并提供2D繪制、圖像處理及用戶接口級別的動畫。
??UIKit包含UIBezierPath(繪制線、角度、橢圓及其它圖形)、UIImage(顯示圖像)、UIColor(顏色操作)、UIFont和UIScreen(提供字體和屏幕信息)等類,它在位圖圖形環境、PDF圖形環境上進行繪制和操作功能,也提供對標準視圖的支持,也提供對打印功能的支持。
??使用UIKit,你只能在當前上下文中繪圖。

Core Graphics

??這是一個繪圖專用的API族,它經常被稱為QuartZ或者QuartZ 2D。Core Graphics 是iOS上所有繪圖功能的基石,包括UIKit(UIKit是對Core Graphics的進一步封裝)。
??使用Core Graphics之前需要指定一個用于繪圖的圖形上下文(CGContextRef),這個圖形上下文會在每個繪圖函數中都會用到。

??至此,我們了解了這兩個框架的基本關系,而這兩個框架中都提到了圖形上下文(圖形場景)。獲得一個圖形上下文是我們完成繪圖任務的第一步,可以將圖形上下文理解為一塊畫布。那么下邊介紹三種獲得圖形上下文的方法:

- (void)drawRect:(CGRect)rect方法

??在此方法中,UIKit框架可以直接繪圖,而Core Graphics可以通過UIGraphicsGetCurrentContext函數獲取當前的圖形上下文。

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

??在此方法中,直接傳入了圖形上下文,但是該上下文不一定是當前的圖形上下文,所以在UIKit框架下繪圖時,需要調用UIGraphicsPushContext()函數將該上下文變為當前上下文,結束時調用UIGraphicsPopContext()函數還原上下文。而Core Graphics框架下可以直接使用該上下文。

UIGraphicsBeginImageContextWithOptions函數

??此函數獲取圖形上下文的規則跟drawRect:方法是一樣的。利用該上下文,你就可以在其上進行繪圖,并生成圖片。調用UIGraphicsGetImageFromCurrentImageContext函數可從當前上下文中獲取一個UIImage對象。記住在你所有的繪圖操作后別忘了調用UIGraphicsEndImageContext函數關閉圖形上下文。
??這里主要解釋一下三個參數的含義。第一個參數表示所要創建的圖片尺寸;第二個參數用來指定生成圖片的背景是否為不透明,YES表示不透明,則得到的是黑色的背景;第三個參數制定生成圖片的縮放因子,這個縮放因子與UIImage的scale屬性所指的含義是一致的。0則表示讓圖片的縮放因子根據屏幕的分辨率而變化。

基于兩大繪圖框架和三種獲取圖形上下文的方法的六種繪圖形式

舉例說明:繪制一個藍色的圓
第一種繪圖形式:基于UIKit框架(即使用UIBezierPath)在UIView的子類方法drawRect:中實現。

- (void) drawRect: (CGRect) rect {
   UIBezierPath* p = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
   [[UIColor blueColor] setFill];
   [p fill];
}

第二種繪圖形式:基于Core Graphics框架在UIView的子類方法drawRect:中實現。

- (void) drawRect: (CGRect) rect {
    CGContextRef con = UIGraphicsGetCurrentContext();
    CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
    CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
    CGContextFillPath(con);
}

第三種繪圖形式:基于UIKit框架(即使用UIBezierPath) 在UIView的子類方法drawLayer:inContext:中實現。

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
    [super drawLayer:layer inContext:ctx];
    UIGraphicsPushContext(ctx);
    UIBezierPath* p = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
    [[UIColor blueColor] setFill];
    [p fill];
    UIGraphicsPopContext();
}

PS:同時此方法必須重寫drawRect:方法,否則上邊的方法不會被調用。
詳細了解這塊的調用邏輯可以看這篇文章
iOS的繪圖之drawRect和drawLayer:inContext
第四種繪圖形式: 使用Core Graphics在drawLayer:inContext:方法中實現同樣操作,代碼如下:

- (void)drawLayer:(CALayer*)lay inContext:(CGContextRef)con {
    CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
    CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
    CGContextFillPath(con);
}

??最后,演示UIGraphicsBeginImageContextWithOptions的用法,并從上下文中生成一個UIImage對象。生成UIImage對象的代碼可以在任何地方被使用,它沒有上述繪圖方法那樣的限制。

第五種繪圖形式: 使用UIKit實現:

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
UIBezierPath* p = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)];
[[UIColor blueColor] setFill];
[p fill];
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

第六種繪圖形式: 使用Core Graphics實現:

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));
CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);
CGContextFillPath(con);
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIKit和Core Graphics可以在相同的圖形上下文中混合使用。在iOS 4.0之前,使用UIKit和UIGraphicsGetCurrentContext被認為是線程不安全的。而在iOS4.0以后蘋果讓繪圖操作在第二個線程中執行解決了此問題。

寫在最后的話

從開始研究這個框架看了很多文章,收獲很多,慢慢從這些文章中一點點的找到它們之間的關系,這個過程是曲折的,但也是喜悅的。后續還會更新,本篇文章只是開始,一點點皮毛。

借鑒的文章

iOS 圖形編程總結
iOS繪圖教程
iOS繪圖框架CoreGraphics分析

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低...
    ShanJiJi閱讀 1,570評論 0 20
  • 原文地址:http://www.cocoachina.com/industry/20140115/7703.htm...
    默默_David閱讀 6,138評論 0 1
  • 緩了幾日沒動靜,報章沒新聞,沒人再找他們麻煩,就連公司的業務也出奇的順利。便找師傅選了黃道吉日,妥妥當當安排了千佑...
    籽鹽閱讀 344評論 0 0
  • 每個人人生當中都會經歷無數次選擇,不同的選擇造就了不同的人生,如何做出最優選擇,如何避開不利選擇,這就變成...
    陌上可妍閱讀 745評論 0 2