iOS繪圖系統(一) UIKit與CoreGraphics

####導語ios

說一下爲何寫這一系列的文章,筆者以前看到動畫就以爲頭大,被CALayer、Transform等名詞弄的暈頭轉向,也查了許多資料,但大部分的資料都是以一個具體的例子來講明動畫的使用,涉及到不少具體的東西,而對不少基本的概念,動畫宏觀方面的闡述的比較少,因此想寫下這一系列的文章,讓初學動畫的人有個快速的宏觀認識。編程

###一、iOS的繪圖系統都有哪些呢?api

iOS主要的繪圖系統有UIKit、Core Graphics(也稱Quartz 2D)、Core Animation、Core Image、OpenGL ES。每個都主要起什麼做用呢?大概介紹一下。性能優化

  • UIKit 最高級的頁面,也是你們頁面佈局常常用到的,好比UIView、UIButton等。能夠經過UI前綴來識別UIKit元素。
  • Core Graphics UIKit下的主要繪圖系統,用於繪製自定義視圖。能夠經過CG前綴來識別Core Graphics元素。
  • Core Animation 提供了強大的2D和3D動畫。
  • Core Image 對圖片進行各類濾鏡處理,好比高斯模糊、銳化等。
  • OpenGL ES 主要用於遊戲繪圖。

###二、視圖繪製與視圖佈局的區別有哪些呢?app

咱們先來理解一下視圖繪製週期的概念,這有助於理解視圖繪製與視圖佈局的區別。工具

  • iOS在運行循環(run loop)中整合全部的繪圖請求,並一次將它們繪製出來。
  • 不能在主線程中進行復雜的操做,不然會形成主線程的卡頓。
  • 不能在主線程以外的主視圖上下文中繪製,只要不是在主視圖上下文中繪製,一些UIKit方法是能夠在後臺線程中使用的。好比能夠在任意線程上使用CGBitmapCreateContext建立CGBitmapContext對象並在裏面繪圖。

視圖繪製,是調用UIView中的drawRect方法。若是一個視圖調用setNeedsDisplay方法,它就被標記爲從新繪製,而且會在下一次繪圖週期中從新繪製,也就是會自動調用drawRect方法。oop

視圖佈局,是調用UIView中的layoutSubviews方法。若是視圖中的子視圖佈局發生變化,須要從新排列,UIKit會自動調用setNeedsLayout方法,也就是對於發生變化的視圖逐層次調用layoutSubviews方法。好比frame發生變化、滾動視圖等。佈局

在畫圖的時候,咱們應該儘可能避免繪製,多使用佈局,這是爲何呢?由於佈局使用的是GPU(GPU基於硬件進行佈局的),而繪製使用的是CPU(基於軟件進行繪製的)。性能

補充:CPU VS GPU字體

  1. 關於繪圖和動畫有兩種處理的方式:CPU(中央處理器)和GPU(圖形處理器)。在現代iOS設備中,都有能夠運行不一樣軟件的可編程芯片,可是因爲歷史的緣由,咱們能夠說CPU所作的工做都在軟件層面,而GPU在硬件層面。
  2. 總的來講,咱們能夠用軟件(使用CPU)作任何事情,可是對於圖像處理,一般用硬件會更快,由於GPU使用圖像對高度並行浮點運算作了優化。因爲某些緣由,咱們想盡量把屏幕渲染的工做交給硬件去處理。問題在於GPU並無無限制處理性能,並且一旦資源用完的話,性能就會開始降低了(即便CPU並無徹底佔用)
  3. 大多數動畫性能優化都是關於智能利用GPU和CPU,使得它們都不會超出負荷。

何時會調用繪製,何時調用佈局呢?我本身的理解是這樣的,視圖在第一次建立的時候,繪製和佈局的都會調用的。若是子視圖由於一些條件的改變,形成佈局的改變,這個時候,系統會自動調用layoutSubviews方法。儘可能避免調用setNeedsDisplay方法。

###三、理解繪圖系統中的座標系

繪圖系統中主要使用兩種座標系。

基於點的座標

原點位於圖層的左上角,向右爲x軸的正方向,向下爲y軸的正方向,一個點的x、y座標以點爲單位。

單位座標系

原點位於圖層的左上角,向右爲x軸的正方向,向下爲y軸的正方向,一個點的x、y座標以相對x軸、y軸的比例爲值,取值範圍爲[0, 1]。錨點(anchorPoint)使用單位座標系。

錨點決定了動畫在變化時,z軸的位置。關於錨點的具體做用,座標變換的具體內容,能夠參考下面的兩篇文章:

座標系講解

座標變換

###四、管理圖形上下文

圖形上下文是什麼意思呢?好比,咱們要畫一幅畫,須要有一張畫布的,而後在畫布上繪製出一幅畫來,圖形上下文就和畫布的概念同樣的。在圖形上下文中包含了大量信息,好比設置畫筆的顏色、設置文本的字體、設置變形等等。

咱們在使用drawRect方法進行繪製的時候,咱們並無建立CGContext,可是咱們卻能夠畫出來本身想要的東西,這是由於,在調用drawRect方法以前,系統爲咱們默認建立了一個圖形上下文(CGContext)。

咱們在繪圖中常常會遇見這幾個名詞,CGContextSaveGState和CGContextRestoreGState,UIGraphicsPushContext和UIGraphicsPopContext,咱們來分別介紹一下。

[[UIColor redColor] setFill];
    CGContextSaveGState(UIGraphicsGetCurrentContext());
    [[UIColor blackColor] setFill];
    CGContextRestoreGState(UIGraphicsGetCurrentContext());
    UIRectFill(CGRectMake(10, 10, 100, 100));

這段代碼設置了畫筆的顏色爲紅色,並保存圖形上下文,以後將畫筆的顏色改爲黑色,並恢復圖形上下文。那麼最後的畫筆顏色是紅色仍是黑色的呢?答案是紅色的,經過這段代碼能看出來CGContextSaveGState和CGContextRestoreGState的用法。

[[UIColor redColor] setFill];
    UIGraphicsPushContext(UIGraphicsGetCurrentContext());
    [[UIColor blackColor] setFill];
    UIGraphicsPopContext();
    UIRectFill(CGRectMake(10, 10, 100, 100));

看下此處的代碼,經過運行,咱們發現最後畫筆的顏色爲黑色,這說明UIGraphicsPushContext並無保存圖形上下文的信息,那麼它的做用是什麼呢?假如你正在圖形上下文中繪製什麼東西,若是這時想要在位圖上下文中繪製徹底不一樣的內容,這就是UIGraphicsPushContext的做用了,切換到一個新的位圖上。當你在新的位圖上,繪製完想要的東西后,在經過UIGraphicsPopContext將剛纔的圖形上下文出棧,也就是恢復到剛纔的繪圖狀態。

切換到另一個上下文,這是一個比較常見的操做,由於經常使用性,系統api提供了UIGraphicsBeginImageContext的快捷方式,它負責將舊的上下文入棧、爲新上下文分配內存、建立新的上下文、翻轉座標系統,並使其做爲當前上下文使用。

###五、 透明、不透明、隱藏

視圖上有三個比較容易混淆的屬性:alpha(透明)、opaque(不透明)和hidden(隱藏)。下面就進行一下深刻的區分。

alpha屬性決定了視圖會經過像素顯示多少信息。alpha爲1表示全部的視圖信息都在像素上表現出來,而alpha爲0表示沒有視圖信息能在像素上表示出來。

opaque,將視圖標記爲opaque,即是向繪圖系統許諾即將繪製的每個像素都要使用全不透明的顏色,這便容許繪圖系統忽略被覆蓋在下面的視圖,這樣能夠改善性能,尤爲是在進行變形的時候。與opaque緊密相關的是clearsContextBeforeDrawing。它的默認值是YES,會在調用drawRect以前將上下問設置爲透明黑底。這樣會避免視圖中產生的任何垃圾數據。

hidden爲YES的話,表示視圖根本不會被繪製。

隱藏和透明視圖不接受觸摸事件,若是想建立一個透明視圖而且接受觸摸事件,能夠這樣來進行設置,設置它的alpha爲一、opaque爲NO且backgroundColor爲你活[UIColor clearColor],來接手觸摸事件。

###六、 繪圖工具神器 下面介紹一款繪圖神器(PaintCode) 安裝完成後,打開工具,界面以下:

圖1-1 paintcode頁面

在頂部的菜單欄,提供了一些常見的形狀,好比矩形、五角星、多邊形。咱們以五角星爲例,簡單介紹一下其用法。拖動五角星到Canvas上,效果以下:

圖1-2所示 繪製五角星

咱們還爲其設置了填充顏色爲紅色的。接下來就是要把作好的圖轉換成代碼導出來,能夠在視圖下方選擇要導出的代碼類型,效果以下:

圖1-3所示 設置代碼導出類型

咱們能夠看下導出類的源碼是怎麼樣的,以下圖:

圖1-4所示 .m文件

該怎麼在本身的工程中使用呢?咱們只須要在本身的工程中建立一個UIView,在UIView的drawRect方法,調用其提供的方法便可。以下所示:

圖1-5所示 使用範例

至此本文結束了,下一篇將經過兩個示例來展現怎麼具體使用UIKit與CoreGraphics進行繪製。

參考文章連接:

https://tech.imdada.cn/2016/06/21/ios-core-animation/

http://www.jianshu.com/p/f4096e8dd52e

相關文章
相關標籤/搜索