概述
Core Graphics Framework
是一套基于C的API框架外永,使用了Quartz作為繪圖引擎。它提供了低級別谭跨、輕量級鹃答、高保真度的2D渲染乎澄。該框架可以用于基于路徑的繪圖、變換测摔、顏色管理置济、脫屏渲染,模板锋八、漸變浙于、遮蔽、圖像數(shù)據(jù)管理挟纱、圖像的創(chuàng)建羞酗、遮罩以及PDF文檔的創(chuàng)建、顯示和分析紊服。Quartz 2D
是Core Graphics Framework
的一部分檀轨。能實現(xiàn)以下的功能
- 畫圖
- 在程序中提供圖形編輯
- 生成或者展示位圖
- 和PDF文檔工作
Painter Model
一個畫圖模型就是將CALayer
上的內(nèi)容渲染到畫布上胸竞,
Graphics context
一個GraphicsContext
對象是一個數(shù)據(jù)類型,封裝了Quartz
圖像到設(shè)備的信息参萄,總共有5種類型的context:
- 窗口
- 位圖
- 打印
- 反鋸齒
這些類型主要是包括:繪制參數(shù)卫枝,設(shè)備相關(guān)信息。
圖形API
OpenGL ES是跨平臺的圖形API讹挎,屬于OpenGL的一個簡化版本剃盾。QuartZ 2D是蘋果公司開發(fā)的一套API.OpenGL ES是應(yīng)用程序編程接口,該接口描述了方法淤袜、結(jié)構(gòu)、函數(shù)應(yīng)具有的行為以及應(yīng)該如何被使用的語義衰伯。也就是說它只定義了一套規(guī)范铡羡,具體的實現(xiàn)由設(shè)備制造商根據(jù)規(guī)范去做.
Core Graphics API所有的操作都在一個上下文中進(jìn)行
獲取當(dāng)前context的方法
調(diào)用UIGraphicsBeginImageContextWithOptions
函數(shù)就可獲得用來處理圖片的圖形上下文。利用該上下文意鲸,你就可以在其上進(jìn)行繪圖烦周,并生成圖片。調(diào)用UIGraphicsGetImageFromCurrentImageContext
函數(shù)可從當(dāng)前上下文中獲取一個UIImage對象怎顾。記住在你所有的繪圖操作后別忘了調(diào)用UIGraphicsEndImageContext
函數(shù)關(guān)閉圖形上下文读慎。UIView
和CALayer
中的渲染方法(比如drawRect
和dispaly
)中,默認(rèn)就是當(dāng)前的context
上實現(xiàn)的槐雾,當(dāng)需要在其他的方法上去對layer
上進(jìn)行的渲染的時候夭委,需要獲取當(dāng)前的山下文,通過func UIGraphicsGetCurrentContext() -> CGContext?
獲取當(dāng)前的上下文募强。
繪圖形式
用Core Graphics之前需要指定一個用于繪圖的圖形上下文(CGContextRef)株灸,這個圖形上下文會在每個繪圖函數(shù)中都會被用到。用UIKit使用的時候自定義UIView
,實現(xiàn)drawRect
方法時擎值,系統(tǒng)會自動的生成一個CGContextRef
慌烧。總共有6種的繪圖方式鸠儿。
-
在UIView的子類方法drawRect:
func drawRect(_ aRect: NSRect) { var p = UIBezierPath(UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)) UIColor.blueColor().setFill() p.fill() }
-
使用Core Graphics,在
drawRect
中實現(xiàn)func drawRect(_ aRect: NSRect) {
let con = UIGraphicsGetCurrentContext() CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100)) CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor) CGContextFillPath(con);
}
CALayer的drawLayer上實現(xiàn) 屹蚊。 view調(diào)用setNeedsDisplay,或者view.layer調(diào)用display进每。和1相似
和2相似,
CALayer
的drawLayer
上實現(xiàn) 通過提供的上下文-
UIGraphicsBeginImageContextWithOptions
實現(xiàn)UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0); let p = UIBezierPath(bezierPathWithOvalInRect:CGRectMake(0,0,100,100)) UIColor.blueColor().setFill() p.fill() let im = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext()
-
使用
UIGraphicsBeginImageContextWithOptions
基于Core Graphics實現(xiàn)UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0); let con = UIGraphicsGetCurrentContext(); CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100)); CGContextSetFillColorWithColor(con, UIColor.blueColor().CGColor); CGContextFillPath(con); let im = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
Quartz2D的數(shù)據(jù)類型
下面列出了Quartz 2D包含的數(shù)據(jù)類型:
CGPathRef
:用于向量圖汹粤,可創(chuàng)建路徑,并進(jìn)行填充或描畫(stroke)
CGImageRef
:用于表示bitmap圖像和基于采樣數(shù)據(jù)的bitmap圖像遮罩田晚。
CGLayerRef
:用于表示可用于重復(fù)繪制(如背景)和幕后(offscreen)繪制的繪畫層
CGPatternRef
:用于重繪圖
CGShadingRef
玄括、CGGradientRef
:用于繪制漸變
CGFunctionRef
:用于定義回調(diào)函數(shù),該函數(shù)包含一個隨機的浮點值參數(shù)肉瓦。當(dāng)為陰影創(chuàng)建漸變時使用該類型
CGColorRef
, CGColorSpaceRef
:用于告訴Quartz如何解釋顏色
CGImageSourceRef
,CGImageDestinationRef
:用于在Quartz中移入移出數(shù)據(jù)
CGFontRef
:用于繪制文本
CGPDFDictionaryRef
, CGPDFObjectRef
, CGPDFPageRef
, CGPDFStream
, CGPDFStringRef
, CGPDFArrayRef
:用于訪問PDF的元數(shù)據(jù)
CGPDFScannerRef
, CGPDFContentStreamRef
:用于解析PDF元數(shù)據(jù)
CGPSConverterRef
:用于將PostScript轉(zhuǎn)化成PDF遭京。在iOS中不能使用胃惜。
CGPath路徑的組成
- 線:實線,虛線--->通過
CGPathAddLines(_:_:_:_:)
等方法 - 點:通過
moveToPoint(_:)
等方法哪雕。 - 淮场:
CGContextAddArc(_:_:_:_:_:_:_:)
和CGContextAddArcToPoint(_:_:_:_:_:_:)
等方法添加弧線 - 曲線:可以通過貝塞爾曲線獲取
CGContextAddArcToPoint(_:_:_:_:_:_:)
,或者自己定義一個貝塞爾曲線 - 最后可以選擇閉合曲線
CGContextClosePath(_:)
路徑的創(chuàng)建
具體步驟是:
- 通過
UIGraphicsGetCurrentContext
獲取上下文,如果是在UIView和CALayer的渲染方法中斯嚎,可以不用獲取 - 在開始繪制路徑前利虫,調(diào)用函數(shù)
CGContextBeginPath
,用CGContextBeginPath
來標(biāo)記Quartz
,因為context一個時間只能有一個path被使用堡僻,如果不使用的話糠惫,會丟棄之前的path - 進(jìn)行線和點的繪制,
CGContextMoveToPoint CGContextAddLineToPoint
- 通過
CGContextAddPath(_:_:)
將路線加到上下文上
繪制路徑
路徑的繪制包括填充和描邊钉疫,在繪制前可以先設(shè)置繪制屬性硼讽,包括線寬,顏色等牲阁。
描邊
描邊的屬性包括:線寬固阁,連接點,是否為虛線城菊。以下是一些常用的描邊函數(shù)
填充
- 填充區(qū)域:填充當(dāng)前路徑時备燃,Quartz將路徑包含的每個子路徑都看作是閉合的。然后凌唬,使用這些閉合路徑并計算填充的像素并齐。但是如果路徑是由幾個重疊的部分組成或者路徑包含多個子路徑,則需一定的規(guī)則來定義填充區(qū)域(具體參考官方文檔)
- 填充模式:Quartz默認(rèn)使用普通混合模式(normal blend mode)客税,也就是多種顏色重疊的時候冀膝,繪制模式。
路徑剪裁
繪制時霎挟,Quartz
只渲染裁剪區(qū)內(nèi)的路徑窝剖,裁剪區(qū)域內(nèi)的閉合路徑是可見的;而在區(qū)域外的部分是不可見的酥夭。
顏色與顏色空間
顏色空間是指一個設(shè)備所能表示的顏色赐纱,通過以下方法
func deviceRGBColorSpace() -> NSColorSpace
-
func deviceCMYKColorSpace() -> NSColorSpace
顏色空間有許多種,常用有RGB熬北,CMY疙描,HSB,CMYK,BGR等.alpha表示存在的對象與新對象如何混合。
CGContextSetAlpha
可以指定全局alpha讶隐。
變化
在繪圖空間上起胰,分為用戶空間和設(shè)備空間。context
是作用在用戶空間的巫延,然后通過CTM(current transformation matrix)映射到設(shè)備空間效五。CTM有三種操作包括平移CGContextTranslateCTM(_:_:_:)
地消,旋轉(zhuǎn)
CGContextRotateCTM(_:_:)
,縮放CGContextScaleCTM(_:_:_:)
。從用戶空間到設(shè)備空間的映射空間可以通過
CGContextGetUserSpaceToDeviceSpaceTransform(_:)
獲取到畏妖。
模式
模式(Pattern)是繪制操作的一個序列脉执,這些繪制操作可以重復(fù)地繪制到一個圖形上下文上。當(dāng)用模式的時候戒劫,`Quartz將Page分割成模式單元格的集合半夷,其中每個單元格的大小不是模式圖片的大小,并使用我們提供的回調(diào)函數(shù)來繪制這些單元格迅细。模式單元格之間可以設(shè)置間距巫橄,并且在模式單元格上被繪制
陰影(Shadow)
陰影包括陰影偏移(iOS和MacOS的坐標(biāo)不一樣),通過CGContextSetShadow(_:_:_:)
和CGContextSetShadowWithColor(_:_:_:_:)
設(shè)置陰影茵典。
具體的步驟如下:
- 保存圖形狀態(tài)
CGContextSaveGState(_:)
- 調(diào)用
CGContextSetShadow(_:_:_:)
- 使用陰影繪制對象
- 恢復(fù)圖形狀態(tài)
漸變
漸變對象主要是兩個CGShadingRef
和CGGradientRef
,CGGradientRef
對象是對CGShadingRef
的封裝湘换,區(qū)別是不需要提供漸變計算函數(shù),只需要提供顏色和位置素組就好
CGGradientRef
的創(chuàng)建和使用
使用過程:
- 創(chuàng)建
CGGradientRef
對象敬尺,提供一個顏色空間,以及兩個以上的位置和顏色數(shù)組 - 調(diào)用
CGContextDrawLinearGradient(_:_:_:_:_:)
或者CGContextDrawRadialGradient(_:_:_:_:_:_:_:)
- 釋放內(nèi)存
使用CGGradient對象
一個CGGradient對象是一個漸變的抽象定義—它簡單地指定了顏色值和位置贴浙,但沒有指定幾何形狀砂吞。我們可以在軸向和徑向幾何形狀中使用這個對象。作為一個抽象定義崎溃,CGGradient對象可能比CGShading對象更容易重用蜻直。沒有將幾何形狀存儲在CGGradient對象中,這樣允許我們使用相同的顏色方案來繪制不同的幾何圖形袁串,而不需要為多個圖形創(chuàng)建多個CGGradient對象概而。
因為Quartz為我們計算漸變,使用一個CGGradient對象來創(chuàng)建和繪制一個漸變則更直接囱修,只需要以下幾步:
創(chuàng)建一個CGGradient對象赎瑰,提供一個顏色空間,一個飽含兩個或更多顏色組件的數(shù)組破镰,一個包含兩個或多個位置的數(shù)組餐曼,和兩個數(shù)組中元素的個數(shù)。
調(diào)用CGContextDrawLinearGradient或CGContextDrawRadialGradient函數(shù)并提供一個上下文鲜漩、一個CGGradient對象源譬、繪制選項和開始結(jié)束幾何圖形來繪制漸變。
當(dāng)不再需要時釋放CGGradient對象孕似。
let locations = 2;
let locations[2] = { 0.0, 1.0 };
let components[8] = { 1.0, 0.5, 0.4, 1.0, 0.8, 0.8, 0.3, 1.0 }
let myColorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
let myGradient = CGGradientCreateWithColorComponents (myColorspace, components,locations, num_locations);
// myStartPoint, myEndPoint起始點和終點
CGContextDrawLinearGradient (myContext, myGradient, myStartPoint, myEndPoint, 0)
CGShadingRef
的創(chuàng)建和使用
CGShadingRef
分為創(chuàng)建和使用
CGShadingRef
的創(chuàng)建
- 獲取顏色空間(
CGColorSpace
) - 設(shè)置起始點和終點
- 起始半徑和終止半徑
-
CGFunctionCreate
這個是關(guān)鍵:需要保證繪制到特低點的顏色值 - 一個bool值踩娘,指定是否用純色來繪制起始點和終點的擴展區(qū)(可選值)
CGShadingRef
的使用
- 設(shè)置
CGFunction
對象計算顏色值 : 也就是計算每一個位置的顏色 - 創(chuàng)建
CGShadingRef
對象 - 裁剪上下文
- 使用
CGShading
對象:CGFunctionEvaluate
的重寫 - 釋放對象
透明
Quartz為每一個上下文維護(hù)一個透明層棧,繪制透明層的步驟如下
- 調(diào)用
CGContextBeginTransparencyLayer(_:_:)
方法表明開始繪制透明 - 在透明層中繪制需要的組合對象
- 調(diào)用
CGContextEndTransparencyLayer(_:)
后,透明才會被繪制上去
CGImageRef類型
CGImageRef
是CGGraphics 的一種重要的數(shù)據(jù)類型喉祭,主要處理的是位圖與圖像的遮罩养渴。創(chuàng)建一個位圖(CGImageRef)時雷绢,Quartz使用以下信息:
- 位圖數(shù)據(jù)源:可以是一個Quartz數(shù)據(jù)提供者或者是一個Quartz圖像源。
- 可選的解碼數(shù)組厚脉。(Decode Array)
- 插值設(shè)置:這是一個布爾值习寸,指定Quartz在重置圖像大小時是否使用插值算法。
- 渲染意圖:指定如何映射位于圖形上下文中的目標(biāo)顏色空間中的顏色傻工。該值在圖像遮罩中不需要霞溪。
- 圖像尺寸
- 像素格式,包括每個分量中的位數(shù)中捆,每個像素的位數(shù)和每行中的字節(jié)數(shù)鸯匹。
如何創(chuàng)建
創(chuàng)建一個位圖對象主要有以下幾種方法:
- 依賴于圖像的數(shù)據(jù)源
- 常用
CGImageCreate
來創(chuàng)建一個我吐 - 從PNG,JPEG創(chuàng)建一個
CGImage
對象,主要通過:CGImageSourceCreateWithURL(_:_:)
泄伪,CGImageSourceCreateImageAtIndex(_:_:_:)
- 從位圖上下文獲取
CGImage
對象殴蓬。調(diào)用CGBitmapContextCreateImage(_:)
- 從一個已存在圖像中創(chuàng)建子圖像
CGImageCreateWithImageInRect(_:_:)
遮罩
一個位圖圖像遮罩定義了如何轉(zhuǎn)換顏色,而不是使用哪些顏色蟋滴。函數(shù)CGImageCreateWithMask
通過將圖像遮罩使用到一個圖像上的方式來創(chuàng)建一個圖像染厅。
總結(jié)
首先CoreGraphics是Quartz的一部分,這部分大多數(shù)是C語言結(jié)構(gòu)的津函,Swift和OC的使用上沒有太大區(qū)別肖粮。而在獲取到了上下文后,關(guān)鍵的是如何去確定Path尔苦,貝塞爾曲線等等涩馆,這部分也可以通過專門的工具,在這推薦一個好的軟件PaintCode允坚,能直接導(dǎo)出Swift代碼和OC代碼魂那。具體可以參考用Sketch和PaintCode快速得到繪制代碼。let's Swift