CoreGraphics with Swift

概述

Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低級別、輕量級、高保真度的2D渲染。該框架可以用于基于路徑的繪圖、變換、顏色管理、脫屏渲染,模板、漸變、遮蔽、圖像數(shù)據(jù)管理、圖像的創(chuàng)建、遮罩以及PDF文檔的創(chuàng)建、顯示和分析。Quartz 2DCore Graphics Framework的一部分。能實現(xiàn)以下的功能

  1. 畫圖
  2. 在程序中提供圖形編輯
  3. 生成或者展示位圖
  4. 和PDF文檔工作

Painter Model

一個畫圖模型就是將CALayer上的內(nèi)容渲染到畫布上,

Graphics context

一個GraphicsContext對象是一個數(shù)據(jù)類型,封裝了Quartz圖像到設(shè)備的信息,總共有5種類型的context:

  1. 窗口
  2. PDF
  3. 位圖
  4. 打印
  5. 反鋸齒
    這些類型主要是包括:繪制參數(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所有的操作都在一個上下文中進行

獲取當(dāng)前context的方法

調(diào)用UIGraphicsBeginImageContextWithOptions函數(shù)就可獲得用來處理圖片的圖形上下文。利用該上下文,你就可以在其上進行繪圖,并生成圖片。調(diào)用UIGraphicsGetImageFromCurrentImageContext函數(shù)可從當(dāng)前上下文中獲取一個UIImage對象。記住在你所有的繪圖操作后別忘了調(diào)用UIGraphicsEndImageContext函數(shù)關(guān)閉圖形上下文。UIViewCALayer中的渲染方法(比如drawRectdispaly)中,默認(rèn)就是當(dāng)前的context上實現(xiàn)的,當(dāng)需要在其他的方法上去對layer上進行的渲染的時候,需要獲取當(dāng)前的山下文,通過func UIGraphicsGetCurrentContext() -> CGContext?獲取當(dāng)前的上下文。

繪圖形式

用Core Graphics之前需要指定一個用于繪圖的圖形上下文(CGContextRef),這個圖形上下文會在每個繪圖函數(shù)中都會被用到。用UIKit使用的時候自定義UIView,實現(xiàn)drawRect方法時,系統(tǒng)會自動的生成一個CGContextRef??偣灿?種的繪圖方式。

  1. 在UIView的子類方法drawRect:

        func drawRect(_ aRect: NSRect) { 
    
             var p = UIBezierPath(UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)) 
    
             UIColor.blueColor().setFill() 
    
             p.fill()
    
          } 
    
    
  2. 使用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);  
    

    }

  3. CALayer的drawLayer上實現(xiàn) 。 view調(diào)用setNeedsDisplay,或者view.layer調(diào)用display。和1相似

  4. 和2相似,CALayerdrawLayer上實現(xiàn) 通過提供的上下文

  5. 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()
    
  6. 使用 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)建路徑,并進行填充或描畫(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路徑的組成

  1. 線:實線,虛線--->通過CGPathAddLines(_:_:_:_:)等方法
  2. 點:通過moveToPoint(_:)等方法。
  3. ?。?code>CGContextAddArc(_:_:_:_:_:_:_:)和CGContextAddArcToPoint(_:_:_:_:_:_:)等方法添加弧線
  4. 曲線:可以通過貝塞爾曲線獲取CGContextAddArcToPoint(_:_:_:_:_:_:),或者自己定義一個貝塞爾曲線
  5. 最后可以選擇閉合曲線CGContextClosePath(_:)

路徑的創(chuàng)建

具體步驟是:

  1. 通過 UIGraphicsGetCurrentContext獲取上下文,如果是在UIView和CALayer的渲染方法中,可以不用獲取
  2. 在開始繪制路徑前,調(diào)用函數(shù)CGContextBeginPath,用CGContextBeginPath來標(biāo)記Quartz,因為context一個時間只能有一個path被使用,如果不使用的話,會丟棄之前的path
  3. 進行線和點的繪制,CGContextMoveToPoint CGContextAddLineToPoint
  4. 通過CGContextAddPath(_:_:)將路線加到上下文上

繪制路徑

路徑的繪制包括填充和描邊,在繪制前可以先設(shè)置繪制屬性,包括線寬,顏色等。

描邊

描邊的屬性包括:線寬,連接點,是否為虛線。以下是一些常用的描邊函數(shù)

描邊函數(shù)

填充

  1. 填充區(qū)域:填充當(dāng)前路徑時,Quartz將路徑包含的每個子路徑都看作是閉合的。然后,使用這些閉合路徑并計算填充的像素。但是如果路徑是由幾個重疊的部分組成或者路徑包含多個子路徑,則需一定的規(guī)則來定義填充區(qū)域(具體參考官方文檔)
  2. 填充模式:Quartz默認(rèn)使用普通混合模式(normal blend mode),也就是多種顏色重疊的時候,繪制模式。

路徑剪裁

繪制時,Quartz只渲染裁剪區(qū)內(nèi)的路徑,裁剪區(qū)域內(nèi)的閉合路徑是可見的;而在區(qū)域外的部分是不可見的。

顏色與顏色空間

顏色空間是指一個設(shè)備所能表示的顏色,通過以下方法

  1. func deviceRGBColorSpace() -> NSColorSpace
  2. 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è)置陰影。
具體的步驟如下:

  1. 保存圖形狀態(tài)CGContextSaveGState(_:)
  2. 調(diào)用CGContextSetShadow(_:_:_:)
  3. 使用陰影繪制對象
  4. 恢復(fù)圖形狀態(tài)

漸變

漸變對象主要是兩個CGShadingRefCGGradientRef,CGGradientRef對象是對CGShadingRef的封裝,區(qū)別是不需要提供漸變計算函數(shù),只需要提供顏色和位置素組就好

CGGradientRef的創(chuàng)建和使用

使用過程:

  1. 創(chuàng)建CGGradientRef對象,提供一個顏色空間,以及兩個以上的位置和顏色數(shù)組
  2. 調(diào)用CGContextDrawLinearGradient(_:_:_:_:_:)或者CGContextDrawRadialGradient(_:_:_:_:_:_:_:)
  3. 釋放內(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)建

  1. 獲取顏色空間(CGColorSpace
  2. 設(shè)置起始點和終點
  3. 起始半徑和終止半徑
  4. CGFunctionCreate這個是關(guān)鍵:需要保證繪制到特低點的顏色值
  5. 一個bool值,指定是否用純色來繪制起始點和終點的擴展區(qū)(可選值)

CGShadingRef的使用

  1. 設(shè)置CGFunction對象計算顏色值 : 也就是計算每一個位置的顏色
  2. 創(chuàng)建CGShadingRef對象
  3. 裁剪上下文
  4. 使用CGShading對象:CGFunctionEvaluate的重寫
  5. 釋放對象

透明

Quartz為每一個上下文維護一個透明層棧,繪制透明層的步驟如下

  1. 調(diào)用CGContextBeginTransparencyLayer(_:_:)方法表明開始繪制透明
  2. 在透明層中繪制需要的組合對象
  3. 調(diào)用CGContextEndTransparencyLayer(_:)后,透明才會被繪制上去

CGImageRef類型

CGImageRef是CGGraphics 的一種重要的數(shù)據(jù)類型,主要處理的是位圖與圖像的遮罩。創(chuàng)建一個位圖(CGImageRef)時,Quartz使用以下信息:

  1. 位圖數(shù)據(jù)源:可以是一個Quartz數(shù)據(jù)提供者或者是一個Quartz圖像源。
  2. 可選的解碼數(shù)組。(Decode Array)
  3. 插值設(shè)置:這是一個布爾值,指定Quartz在重置圖像大小時是否使用插值算法。
  4. 渲染意圖:指定如何映射位于圖形上下文中的目標(biāo)顏色空間中的顏色。該值在圖像遮罩中不需要。
  5. 圖像尺寸
  6. 像素格式,包括每個分量中的位數(shù),每個像素的位數(shù)和每行中的字節(jié)數(shù)。

如何創(chuàng)建

創(chuàng)建一個位圖對象主要有以下幾種方法:

  1. 依賴于圖像的數(shù)據(jù)源
  2. 常用CGImageCreate來創(chuàng)建一個我吐
  3. 從PNG,JPEG創(chuàng)建一個CGImage對象,主要通過:CGImageSourceCreateWithURL(_:_:),CGImageSourceCreateImageAtIndex(_:_:_:)
  4. 從位圖上下文獲取CGImage對象。調(diào)用CGBitmapContextCreateImage(_:)
  5. 從一個已存在圖像中創(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容