Core Animation學習總結

文件夾:
  1. The Layer Beneath
    1. The Layer Tree(圖層樹)
    2. The Backing Image(寄宿層)
    3. Layer Geometry(圖層幾何學)
    4. Visual Effects(視覺效果)
    5. Transforms(變換)
    6. Specialized Layers(專有圖層)
  2. Setting Things in Motion
    1. Implicit Animations(隱式動畫)
    2. Explicit Animations(顯式動畫)
    3. Layer Time(圖層時間)
    4. Easing(緩衝)
    5. Timer-Based Animation(基於定時器的動畫)
  3. The Performance of a Lifetime
    1. Tuning for Speed(性能調優)
    2. Efficient Drawing(高效畫圖)
    3. Image IO(圖像IO)
    4. Layer Performance(圖層性能)



Core Animation 之 CALayer
The Layer Tree(圖層樹)

一、圖層與視圖的差異:
  • 視圖是以樹的數據結構來管理層級關係的。而圖層相同也是以樹的數據結構來管理層級關係
  • 視圖在程序中以UIView及其子類來表示。而圖層以CALayer及其子類專用 圖層來表示
  • UIView老是與CALayer是一一相應的關係,因此本質上,iOS上界面上的內容的呈現與動態其實是經過CALayer來實現的,而UIView是封裝了CALayer的基礎上加入了事件響應、佈局等高級功能。


二、關於視圖層級、圖層樹、呈現樹、渲染樹
  • 視圖層級:主要負責實現事件響應、佈局等功能,因爲視圖封裝圖層。圖層向視圖暴露部分編程接口與屬性,因而經過改動視圖的效果可以間接改動圖層的屬性。

  • 圖層樹:負責定義界面圖形的繪製、動畫效果,iOS是有一個繪製週期的——60FPS,也就是說圖層樹負責保存這個週期內的相關屬性的改動,而到了週期結束要進行繪製的時候,才把圖層樹的數據模型更新到呈現樹中。
  • 呈現樹:肯定當前屏幕上界面圖形的詳細效果。用於保存當前屏幕的圖形的顯示屬性,每隔一個繪製週期和圖層樹同步一次。
  • 渲染樹:iOS系統會專門建立一個進程來運行圖形渲染的任務,當隨意APP(包含系統App)需要圖形渲染的時間,它們就會把渲染任務發送到該線程去運行渲染。

因此以上四層。每一層都負責不一樣的任務,其數據流是視圖-》圖層-》呈現樹-》渲染樹。

並且繪製週期60FPS也是會隨着系統的狀態而變化的,若系統資源超載,而會經過下降繪製次數來確保系統能穩定執行。html


三、視圖動畫
視圖動畫是顯式,因爲UIView默認把CALayer的隱式動畫禁止掉了。因此要經過動畫Block的形式才幹取消動畫的限制。(動畫block實際上就是曾經的動畫棧)。
並且視圖能實現的動畫僅僅是圖層所開放的一部分,都是2D動畫,因此視圖動畫的效果會稍稍簡單。

四、圖層動畫
圖層動畫是隱性動畫。僅僅要改動圖層的屬性。其變化都會以默認的漸變形式呈現出來(詳細原理見《隱式動畫》)。並且圖層動畫支持不少其它視圖動畫沒法實現的效果。如:
  • 陰影、圓角、帶顏色的邊框
  • 3D變化
  • 非矩形範圍
  • 透明遮罩
  • 多級非線性動畫。

五、更適宜使用CAlayer呈現內容的場景
因爲UIView與CALayer都可以呈現內容。儘管CALayer不能直接實現事件響應。但開發人員也可以經過hit-test機制的原理來本身實現事件響應,那什麼場景更加適合用CALayer而不是UIView呢?例如如下所看到的:
  • 開發同一時候可以在MAC、iOS上執行的跨平臺應用
  • 使用多種CALayer的子類(專有圖層),並且不想建立額外的UIView去封裝
  • 作一些對性能特別挑剔的工做,如對UIView一些可忽略不計的操做都會引發顯著的不一樣(也可以經過OpenGL來解決)。


The Backing Image(寄宿層)

一、寄宿層&Contents屬性
CALayer有一個名曰Contents的屬性,這個屬性是與寄宿層相相應了,而contents屬性指向的對象必須爲CGImageRef類型(一個指向CGImage結構的指針),因此寄宿層是用來展現圖片所用的。例如如下狀況會調用寄宿層:
  • 顯示圖片
  • core Graphics
core Graphics可以實現本身定義繪製,但一般不建議那麼作,因爲core Graphics繪製會默認生成一個繪製專用的存儲空間,而這空間有十多M那麼多。會佔用大量內存,因此Apple不建議實現空的core Graphics更不建議在core Graphics實現不屬於該方法的代碼。

二、contentGravity屬性
與UIView的contentMode屬性相相應,用於調整圖片的佈局,支持一下常量值:
  • kCAGravityCenter
  • kCAGravityTop
  • kCAGravityBottom
  • kCAGravityLeft
  • kCAGravityRight
  • kCAGravityTopLeft
  • kCAGravityTopRight
  • kCAGravityBottomLeft
  • kCAGravityBottomRight
  • kCAGravityResize
  • kCAGravityResizeAspect
  • kCAGravityResizeAspectFill

三、contentsScale
contentsScale屬性定義了寄宿層的像素尺寸和視圖大小比例,默認是1.0(一個點一個像素),在retina屏幕得設置在2.0(一個點兩個像素)。在plus設備上得設備爲3.0(一個點3個像素)。
但若contentGravity設置瞭如kCAGravityResizeAspectFill本身主動適配大小的屬性後,contentsScale會不起做用。因此不能依靠contentsScale來作縮放的操做,縮放仍是得交給transform或者affineTransform。


三、maskToBounds
該屬性與UIView的clipsToBounds屬性相相應。都是應用於將超出圖層邊界的子圖層的內容進行裁剪。

這裏需要一點需要注意的,但咱們實現radiusCorner時,實際上就是經過設置背景顏色來實現的。而與maskToBounds結合纔是真正把邊角內容裁剪掉,但radiusCorner+maskToBounds結合使用會引起離屏渲染。因此在radiusCorner知足要求。就不要再調用maskToBounds。

四、contentsRect
CALayer的contentsRect贊成咱們在圖層邊框內顯示寄宿圖的一個子域,而contentsRect是一個相對值屬性,如{0,0。1,1}表示整個寄宿圖,這樣的座標系統也叫單位。例如如下簡述iOS下的三種座標系統單位:
  • 點:點是虛擬的像素,也叫邏輯像素。在不一樣的設備上一個點所表明的像素點是不同的。如普通屏幕一個點就是一個像素,而retina屏幕一個點就是兩個像素。
  • 像素:實際的物理像素座標。
  • 單位:一種相對的座標,優勢就是應用相對值,方便移植。
contentsRect有一種經典的使用方法——image sprites(圖片拼接,常用於遊戲),這種使用方法就是用來實現一次性載入多張圖片的。因爲每一張圖片的使用前都要通過,載入——》壓縮——》呈現,的一個過程中載入和壓縮是十分耗時的,載入消耗IO,壓縮算法的複雜會添加CPU的消耗,因此想遊戲這種App需要載入解壓大量的圖片時,可以把所有圖片整合成一張圖片來載入解壓,而後經過contentsRect裁剪出子圖,並顯示,可以優化載入解壓的過程。

五、contentsCenter
contentsCenter的名字事實上有一點的誤導性,事實上際上與UIView的Stretching屬性相相應。用來實現寄宿層的縮放時的呈現效果。也是一個相對值單位。


六、customs drwaing
除了經過CGImage設置到contents的方式來實現寄宿層。還可以經過Core Graphics來直接繪製寄宿層,但這樣的方式十分消耗內存不建議使用。
CALayer有一個可選的Delegate屬性。實現了CALayerDelegate,但CALayer需要又一次繪製,則調用它的displayLayer方法(與UIView的setNeedDispaly相相應),就會調用其代理方法drawLayer:inContext(與UIView的drawRect相相應)。

若在視圖層中,僅僅要用戶實現了drawRect那麼僅僅要屏幕需要又一次繪製那麼該方法都會被默認調用。git


Layer Geometry(圖層幾何學)

一、佈局
UIView的三個重要佈局屬性:frame、bounds、center
CALayer的三個重要的佈局屬性:frame、bounds、position
可以看出UIView與CALayer的佈局屬性是一一相應的,而惟一有啥區別的就是錨點的命名,UIView爲center,而CALayer爲position,但錨點最開始都是默以爲圖形的中心。
當中frame實際上就是一個虛擬屬性,其由bounds與center/position計算所得。因此改動bounds與center/position也會影響到frame的數值。
還有無論是視圖仍是圖層。在屏幕上無論怎麼變形,本質上其仍是一個矩形。但在旋轉的狀況下。frame的數值是會事實變更的,例如如下圖:



二、錨點
錨點屬性是用來指定圖層相對於父圖層的位置。也可以理解爲利用圖層的句柄。默以爲圖層的中心但也可以改動。在圖層中改動了錨點會產生移動(隱性動畫),相同的錨點也是一個相對值。
例如如下。爲錨點的實驗效果圖:

圖一:時分秒針直接以圖層的中點爲錨點,因爲旋轉時也以其爲中心,效果例如如下:


圖二:將錨點改動成指針的尾端


圖三:改動錨點後的旋轉效果。


三、座標系
因爲每個圖層都有本身的座標系,因此CALayer也提供了一系列的方法用於一個點在不一樣的座標系之間轉換,這些方法特別適合於子圖層與父圖層之間的座標轉換。




事實上UIView與CALayer都有zPosition。但由於UIView只支持2D變換,因此UIView的zPosition只適合於用來做圖層的調整,但更加建議用UIView提供的視圖數組管理方法來調整視圖的繪製順序來調整。而CALayer的zPosition是一個重要的三維座標系。

四、Hit Testing
Hit Testing是iOS中一個十分重要的機制,用於檢索點擊了的目標圖標,與響應鏈條相互搭配的話。就會將終於目標圖標設置爲第一響應者。Hit Testing提供了兩個核心的方法:
  • containPoint:(用於直接推斷某個點是否屬於某個圖層)
  • -hitTest(經過遞歸遍歷子對象的方式來直接返回目標圖層)

五、本身主動佈局
對於UIView。經過UIView暴露出來的UIViewAutoresizingMask和NSLayoutConstraint來實現本身主動佈局。

但對於CALayer,則需要手動來操做實現,當中最爲簡單的方法就是實現CALayerDelegate的例如如下函數:
- (void)layoutSublayersOfLayer:(CALayer *)layer;
在該方法內依據當前layer的屬性來計算調整來實現本身主動佈局。

因爲CALayer實現本身主動佈局不方便,因此這也是爲何更加建議使用UIView來實現界面的構建。

Visual Effects(視覺效果)——本節探討能夠經過CALayer實現的附加視覺效果

一、圓角
CALayer有一個叫作cornerRadius的屬性控制圖層角的曲率,這個曲率僅僅影響背景顏色而不影響圖片或者子圖片。圓角的計算原理就是一個以CALayer的中點,曲率所設的半徑的原與矩形的交集就是目標圖形。
另外一個名曰maskToBounds屬性,就是實現將圖層裏面邊界外的圖形全部分割丟棄。
因此經過cornerRadius+maskToBounds組合可以實現圓角,但同一時候會引起離屏渲染,如果小量的離屏渲染還好,但如滾動欄的場景,開會有大量的離屏渲染的任務產生,就會嚴重影響性能,這一點也是注意優化的。詳細效果例如如下圖所看到的:




二、圖層邊框
經過設置CALayer的borderWidth與borderColor兩個屬性可以改動邊框的效果。

效果例如如下:算法





三、陰影
陰影是一種能達到圖層深度暗示效果的裝飾。

CALayer提供下面參數來定製陰影的效果:數據庫

  • shadowOpacity:設置一個大於零的數值,那麼陰影就會顯示在圖層如下(默以爲0)。
  • shadowColor:設置陰影的顏色(默認黑色)
  • shadowOffset:設置陰影的偏移量(默認{0。-3})
  • shadowRadius:設置陰影模糊度,數值越大。陰影的模糊度越高(默以爲0)。曲率越大,陰影效果越明顯。
shadowRadius的設置效果圖例如如下:


有一點需要注意的,就是陰影的繪製是屬於離屏繪製。是比較效果資源的。因此必定要下降同一屏幕進行大量陰影繪製的狀況。


四、陰影裁剪
圖層的陰影不少其它是繼承於內容的外形,而不是依據邊界和角半徑來肯定。爲了計算出陰影的形狀。core animation會將寄宿層也考慮在內。

但若直接maskToBounds來裁剪,會把陰影效果也裁減掉。編程

爲了解決以上問題。可以經過專門引入一個陰影圖層來解決,詳細效果例如如下:

圖一:直接maskToBounds裁剪會把陰影效果一併裁剪掉。


圖二:經過加入一個另外的陰影圖層在如下,然它來實現陰影。而詳細的內容圖層就直接maskToBounds裁剪。


圖三:終於既能實現裁剪,又能實現陰影。


PS:無論是陰影仍是圓角裁剪都會引起離屏渲染,大量的該類型的圖形需要渲染的話。會減低幀率。


五、shadowPath 屬性
陰影並必定是方形的。咱們也可以經過shadowPath來定製本身想要的陰影形狀。詳細效果例如如下所看到的:




六、圖層蒙版
經過masksToBounds屬性。咱們可以實現邊界裁剪,但咱們還需要更加靈活的裁剪需求的時候就可以經過圖層蒙版來實現。CALayer提供一個mask的屬性來解決一個問題。而mask原本就是指向還有一個圖層的指針。其詳細原理例如如下圖所看到的:




從上圖效果可以知道mask舒心僅僅關心形狀的交集,而顏色仍是由原來的圖形的顏色決定。

另外一點需要注意的是圖層蒙版也會引起離屏渲染,會帶來性能問題,因此使用的時候也得多加註意。


七、拉伸過濾
當咱們視圖顯示一個圖片的時候。都應該以正確的比例,正確的1:1像素顯示在屏幕上。緣由例如如下:
  • 能夠顯示更好的畫質,像素既沒有被壓縮也沒有被拉伸
  • 能更好使用內存,因爲這就是你要存儲的東西
  • 最好的性能表現,CPU不需要爲此額外的計算 
但有時候咱們就需要縮略圖。所專門另外存儲縮略圖這對內存來講。

這時就可以經過CALayer的minificationFilter(縮小濾波器)和magnificationFilter(方法濾波器)屬性實現圖形的縮放算法。當中提供下面三種默認的縮放算法:數組

  • kCAFilterLinear(雙線性濾波算法,默認算法)
  • kCAFilterTrilinear(三線性濾波算法)
  • kCAFilterNearest(近期濾波算法)
對於大圖的縮放,採用kCAFilterLinear、kCAFilterTrilinear,效果會比較好。

對於小圖、較少斜線的圖的縮放,。採用kCAFilterNearest效果比較好。

圖一:採用kCAFilterLinear的方法濾波器算法的效果。


圖二:採用kCAFilterNearest的放大濾波器算法的效果:




八、透明組
UIView有一個alpha屬性類肯定視圖的透明度。而CALayer有一個與之相應的屬性——opacity。這兩個屬性都會影響到子圖層。例如如下圖所看到的:
當咱們將view2的alpha數值設置爲0.5,這時候,對於label所處的點的顏色計算公式爲:50%label + 25%view + 25%background,因此就是灰色偏白的顏色。
若想整個圖層的色調保持一致,可以經過將shouldRasterize屬性設置爲YES,那麼圖層及其子圖層將被整合成一個整體的圖片。效果例如如下:

圖一:shouldRasterize屬性設置爲默認值NO的效果。


圖二:shouldRasterize屬性設置爲默認值YES的效果。




Transforms(變換)

一、仿射變換
UIView相應的transfrom屬性是一個CGAffineTransfrom類型。用於實現二維空間旋轉、平移、縮放、斜切。
而CALayer的transform屬性是一個CATransforms3D。能應用3維空間進行旋轉、平移、縮放、斜切等效果。
當中,仿射變化的數學原理例如如下:


只是iOS爲了運算的方便。已經提供了三個標準方法分別用於實現旋轉、縮放。平移,而斜切得靠原生運算來實現。


當中有一點需要注意的,就是旋轉的angle是以弧度製爲單位的。

iOS系統提供下面方法來實現混合變換,能同一下面的組合函數實現複雜的變形模式:

圖一:建立一個空的變換結構體。




圖二:不斷疊加變換結構體


圖三:直接將兩個變換結構體合併


剪切變換的效果與事實上現代碼:




二、3D變化
3D變化與2D變化是十分類似的,不一樣的僅僅是3D變換是3個維度的,加入了Z軸。其數學原理例如如下:


這樣的矩陣運算仍是挺麻煩的。因此iOS系統提供給咱們便捷的方法:


相同也會有變換疊加的方法,當中旋轉的時候必定要注意當前的旋轉的參考軸,順時針旋轉爲正值,逆時針旋轉爲負值。




三、透視投影
在真實的世界中,當物體遠離咱們。由於視角的緣由,其會變小。因此爲了讓3D效果更佳真實,需要引入投影變換,儘管core animation並無提供給咱們,但十分簡單,其數學實現例如如下:


僅僅要將m34 = -1/d, d= 500~1000,(d越小越失真,d越大透視效果越弱)。


圖3.1:沒實現透視投影的旋轉效果。



圖3.2:實現了透視投影的旋轉效果。



四、滅點
在人的視覺中。當物體離人越遠則會變得越小,當接近無窮遠的時候就會匯聚成一個不可見的點,這個點就叫滅點。現實生活中,這個點一般就是中心點,因此在程序中咱們也要讓圖形的滅點集中在屏幕的中點,例如如下所看到的:


而實現方式則是。首先加入圖形的時候先以屏幕中點爲錨點加入,而後經過transfrom來說圖層移動到恰當的位置。


五、sublayerTransform
sublayerTransform是一種將所有對應的配置統一設置到該圖層的所有子圖層的便捷屬性。

六、3D座標下的圖層背面
在3D座標下,圖層的背面也是會繪製的,而且是正面的鏡像。
咱們可以經過CALayer的doubleSided屬性來決定是否運行雙面繪製。


七、扁平化圖層
假設父圖層的座標發生變換,那麼子圖層也會隨着父圖層而進行相同的變換,如7.1圖所看到的。但有時咱們僅僅想變換父圖層並不想變換子圖層。這時就得作相對變換來抵消掉父圖層的變換。讓視覺效果看起來子圖層是精巧的。例如如下圖所看到的:
圖7.1:2D相對旋轉理論圖


圖7.2:2D相對旋轉效果圖


圖7.3:3D相對旋轉理論圖


圖7.4:3D相對旋轉實際效果圖


咱們可以看出,在2D座標系下。相對變換是合理的。但在3D座標系下,相對變換的結果並不如預想的同樣,爲何呢?
這是因爲core Animation圖層儘管存在於3D空間以內,但並不是每一個圖層都存在於同一個3D空間之間。

而用戶是以當前window所在的3D座標系爲參考的,這時7.4圖的3D座標系與window的已經不重合的,因此在咱們的視覺裏面,就是看不到預想的效果,這就是圖層扁平化。緩存

圖層扁平化讓core animation建立複雜的3D場景變得十分困難,因爲很是難使用圖層樹去建立一個3D結構的層級關係——將所有的場景下的3D都保持一樣的3D座標系。
只是CALayer提供一個專用圖層——CATransformLayer來解決問題,所有加入到該圖層內的3D圖形都共享一個標準座標系。



八、3D場景下的光亮和陰影
略。臨時不懂。

九、3D場景下的點擊事件
在處理點擊事件,必定要注意點擊響應是由UIView中的圖層結構來決定的,而不是CALayer在屏幕上的呈現效果,因此得注意事件攔截的順序。
可以經過設置userInteractionEnabled以及簡單的視圖覆蓋來實現點擊事件正確的傳遞。


Specialized Layers(專有圖層)

一、CAShapeLayer


二、CATextLayer


三、CATransformLayer


四、CAGradientLayer


五、CAReplicatorLayer


六、CAScrollLayer


七、CATiledLayer


八、CAEmitterLayer


九、CAEAGLlayer


十、AVPlayerLayer


Core Animation 之 動畫
Implicit Animations(隱式動畫)

一、隱式動畫&事務
Core Animation基於一個若是,就是屏幕上的所有圖形都可以作動畫,而且這樣的動畫不需要開發人員去設置,會本身主動實現。這也是爲何直接改動CALayer的屬性會以一種漸變的形式來更新到一個新的值。
這樣的僅僅需要改動圖層的數值就會引起動畫的形式來更新到新數值的動畫稱爲隱式動畫。
而這樣的定義了動畫的詳細呈現效果的機制,就稱爲事務。
由於CALayer是默認開啓了隱式動畫的。而若咱們在CALayer上調用顯式動畫的話,就考慮到隱式動畫對效果的影響,進而決定是否需要取消隱式動畫。

二、動畫Block
UIView封裝了CALayer。但UIView禁止了隱性動畫,因此開發人員需要在UIView上實現顯性動畫。

在iOS4.0以前,UIView採用動畫棧來管理顯示。後來提供了動畫Block這個更加便捷的方式。但原理都是同樣的。性能優化


三、圖層行爲
咱們把改變CALayer屬性時本身主動應用的動態稱爲行爲。一組行爲的運行步驟例如如下所看到的:
  1. CALayer調用-actionForKey:方法,傳遞屬性名稱。
  2. 檢查CALayer是否持有實現了CALayerDelegate的代理對象(需要實現actionForLayer:forKey方法),如有直接調用並返回結果,若無繼續下面步驟。
  3. 檢查包括屬性名稱相應行爲映射的actions字典。如有則返回,無則繼續
  4. 在style字典接着搜索屬性名。如有這返回,無則繼續
  5. 調用屬性的標準行爲defaultActionForKey方法
通過以上的整個流程,要麼actionForKey返回nil則無動畫效果,要麼就是返回CAAction,而後CALayer利用它實現動畫。
所以可以推進出UIView是怎樣禁止隱式動畫的,就是講CALayer的delegate設置爲自身。而後在actionForLayer:forKey方法中返回nil。

  • 禁止隱式動畫的兩個方法:
    • 依據圖層行爲的原理,實現代理方法actionForLayer:forKey強制返回nil。
    • 經過設置[CATransaction setDisableActions:YES]來實現禁止隱式動畫

四、呈現與模型
在iOS中。屏幕每秒鐘又一次刷新屏幕60次。

因此Core Animaiton就需要在設置一次新值和新值生效之間,對屏幕上的圖層進行又一次組織。微信

正是覺得上面的機制的存在。因此纔會有iOS纔會有圖層以及呈現層之間的關係,圖層更像是model,而呈現層就是view,Core Animation就是Controller,因此在一個繪製週期內,圖層負責收集與保存用戶對屬性的改動,到繪製時刻時。就將圖層的數據覆蓋到呈現樹。

咱們可以經過CALayer的 -presentationLayer方法來獲取正在屏幕上顯示的呈現樹的數據,儘管通常不需要。但在下面狀況下會比較有做用
  • 作基於定時器的動畫時。而不不過基於事務的動畫。這時準備地知道當前時刻的圖層的顯示位置是十分實用的
  • 假設你想作圖層的響應輸入,可以經過-hitTest方法來推斷制定圖層是否被觸摸。這時候對呈現圖層調用-hitTest會更加有效,因爲呈現樹就是當前屏幕上的圖形實際的位置。


Explicit Animations(顯式動畫)

一、Core Animation的類圖架構


  • CAAnimation實現了CAMediaTiming協議。自己並無作什麼工做。主要實現動畫的時間相關的屬性以及計算函數(緩衝)
  • CATrasition描寫敘述變換的對象
  • CAAnimationGroup封裝屬性動畫的隊列。
  • CABasicAnimation基礎屬性動畫
  • CAKeyFrameAnimation關鍵幀動畫

二、基礎屬性動畫
基礎動畫主要由CABasicAnimation實現,由上圖可知道。而CABasicAnimation繼承於CAPropertyAnimation屬性動畫,經過設置下面三個數值以及其它的選項,就能夠實現本身主動動畫:
  • fromValue
  • toValue
  • byValue
當中toValue與byValue不能同一時候使用,toVaule是絕對值,byValue是相對值。

屬性動畫都是針對關鍵幀的動畫。也就是說僅僅關心出發點與結束點,中間的過渡可以本身生成也可以默認。網絡


三、關鍵幀動畫
CAKeyFrameAnimation用於實現關鍵幀動畫,能經過設置其animations數組來定義每個關鍵幀的位置,也可以直接經過path屬性來定義運動的路徑。


四、affineTransform屬性
若咱們讓一個圖形沿着曲線運動。可以經過設置affineTransform。讓其能沿着曲線的切線運動從而讓運動更加真實。先後效果圖例如如下圖所看到的:



五、虛擬屬性
屬性動畫其實是針對關鍵路徑而不是一個鍵的。這就意味着可以對子屬性甚至虛擬屬性作動畫。

如若咱們想實現旋轉的效果,原本咱們需要在keyPath上設置「transform」,
若使用虛擬屬性。可以直接在keyPath上直接設置「transfrom.rotation」,這樣在設置formValue與toValue時就可以直接設置弧度叫的值。
事實上transfrom.rotation這個屬性是並不存在的,而是core aniamiton本身主動依據CAValueFunction來又一次計算transform的數值所得,正因爲如此才稱之爲虛擬屬性。


六、動畫組
CAAnimationGroup是一種組合動畫的解決方式。經過CAAnimationGroup加入沿曲線運動與顏色變化的動畫。



七、過渡
略。


八、在動畫的過程當中取消動畫
Core Animation提供了一部分的方法來實現動畫加入以及移除。例如如下圖所看到的:
- (CAAnimation *)animationForKey:(NSString *)key;  //實現動畫的加入,當中key不只可以用來訪問動畫,還可以用來移除動畫
- (void)removeAnimationForKey:(NSString *)key;  //移除Key指定的動畫
- (void)removeAllAnimations;  //移動CALayer已經加入的所有動畫
Layer Time(圖層時間)

一、CAMediaTiming協議
CAMediaTiming協議定義了在一段動畫內控制逝去時間的屬性集合。

CALayer和CAAnimaition都實現了該協議,因此時間可以被隨意圖層或者一段動畫的類所控制。


CAMediaTiming協議下定義的一些核心屬性:
  • duration:定義一段動畫的持續時間
  • repeatCount:定義一段動畫的反覆次數
  • repeatDuration:制定動畫反覆一段制定的時間
  • autoreverses:制定在每次間隔交替循環的過程當中本身主動回放
可以經過將repeatCount或者repeatDuration設置爲INFINITY來實現動畫無限循環播放。但不能同一時候使用這兩個屬性。


二、相對時間
在Core Animation中,時間是相對的,每個動畫都有本身的描寫敘述時間,可以獨立的加速、延遲或者偏移,當中有下面關鍵屬性:
  • beginTime:動畫的開始時間。但不是絕對時間,而是一個相對時間,就是從該動畫加入到可見層的那一刻開始測量,默認是零。
  • speed:時間倍速,默認是1.0,若設置爲2.0而二倍速前進。那麼對於一個duration爲1.0的動畫,實際上0.5s就已經完畢。
  • timeOffset:讓動畫直接快進到某個時間點進行,使用它要注意是否有speed的參與而改變的duration
  • duration:動畫的播放時間。

三、fillMode
當一個圖層產生動畫,實際上就是呈現層在運行動畫。那麼。當呈現層運行完動畫是否要講當前屬性的值覆蓋會圖層。這樣的行爲就稱爲fill mode,這個由開發人員決定:
  • kCAFillModeForwards:(保持結束後的值)
  • kCAFillModebackwards:(保持結束前的值)
  • kCAFillModeBoth:(包含以上兩種狀況)
  • kCAFillModeRemoved:(默認。當不在播放動畫時,則顯示回圖層的屬性值)


四、全局時間與本地時間
CALayer 或者 CAGroupAnimation 調整 duration repeatCount / repeatDuration 屬性並不會影響到子動畫。但是 beginTime timeOffset speed 屬性將會影響到子動畫。
每個 CALayer CAAnimation 實例都有本身 本地 時間的概念。是依據父圖層/動畫層級關係中的 beginTime timeOffset speed 屬性計算。

CoreAnimation有一個 全局時間 的概念。也就是所謂的 馬赫時間 (「馬赫」其實是iOS和Mac OS系統內核的命名)。
CACurrentMediaTime 函數來訪問馬赫時間:
CFTimeInterval time = CACurrentMediaTime();
該值返回的是一個相對值,與現實的時間無關。但可以經過它來比對不一樣動畫之間的時間差,iOS提供下面方法來進行不一樣圖層之間本地時間的轉化:
- (CFTimeInterval)convertTime:(CFTimeInterval)t fromLayer:(CALayer *)l; 
- (CFTimeInterval)convertTime:(CFTimeInterval)t toLayer:(CALayer *)l;
經過以上知識可以實現同步不一樣圖層的speed,timeOffset、beginTime的動畫。


五、暫停、倒回和快進的實現
設置動畫的 speed 屬性爲0可以暫停動畫。但不能再加入後再改動。不然會報錯。
但咱們可以經過下面的設置來實現一些調試:
self.window.layer.speed = 100;

六、手動動畫
將speed設置爲0讓動畫中止播放。而後改動timeOffset來切換不時間的動畫序列。從而實現手動切花動畫的效果。

Easing(緩衝)——讓動畫更加平滑天然

一、CALayer、Animation的緩衝動畫與CAMediaTimingFucntion
首先需要設置 CAAnimation timingFunction 屬性,是 CAMediaTimingFunction 類的一個對象。假設想改變隱式動畫的計時函數,相同也可以使用 CATransaction +setAnimationTimingFunction: 方法。來實現緩衝函數。當中有下面默認的緩衝函數:
kCAMediaTimingFunctionLinear            //線性
kCAMediaTimingFunctionEaseIn            //緩進
kCAMediaTimingFunctionEaseOut           //緩出
kCAMediaTimingFunctionEaseInEaseOut     // 緩進 緩出
kCAMediaTimingFunctionDefault           //默認的效果與 kCAMediaTimingFunctionEaseInEaseOut相似,但效果更佳不明顯

二、UIView的緩衝動畫
經過設置UIView的options參數加入例如如下常量也可以實現緩衝動畫的效果:
UIViewAnimationOptionCurveEaseInOut 
UIViewAnimationOptionCurveEaseIn 
UIViewAnimationOptionCurveEaseOut 
UIViewAnimationOptionCurveLinear


三、緩衝和關鍵幀動畫
CAKeyframeAnimation 有一個 NSArray 類型的 timingFunctions 屬性。咱們可以用它來對每次動畫的步驟指定不一樣的計時函數。但是指定函數的個數必定要等於 keyframes 數組的元素個數 減一 ,因爲它是描寫敘述每一幀之間動畫速度的函數。


四、本身定義緩衝函數
臨時不討論。


Timer-Based Animation(基於定時器的動畫)——咱們可以經過事務來實現動畫。設置關鍵幀,讓中間的過渡本身主動計算得出。也可以基於定時器來設置每一個繪製週期的變換來實現動畫。


iOS提供一下兩種形式來實現基於定時器的動畫:
  • NSTimer  :並不是依據實際幀率來運行,因此CADispaly是更好的解決方式
  • CADispaly  :依據實際的幀率來運行。更加適合

但無論是NSTimer仍是CADispaly本質上都是基於runloop,NSTImer把每個時間觸發的事件註冊到runloop裏面。以待制定。

而CADisplay則把任務直接嵌套進繪製操做以前。



Core Animation 之 性能優化
Tuning for Speed(性能調優)

一、CPU &  GPU
CPU(中央處理器)和GPU(圖形處理器)都是能用來處理。

總的來講。咱們可以用軟件(使用CPU)作不論什麼事情,但是對於圖像處理,通常用硬件會更快,因爲GPU使用圖像對高度並行浮點運算作了優化。

因爲某些緣由,咱們想盡量把屏幕渲染的工做交給硬件去處理。問題在於GPU並無無限制處理性能。而且一旦資源用完的話,性能就會開始降低了(即便CPU並無全然佔用)。

性能優化的本質就會合理地利用CPU與GPU,使他們不會超出負荷。


Core Animation處於iOS的核心地位,無論是應用內仍是應用外都會用到它。因此iOS特別設計了一個進程來運行渲染相關的任務,也叫渲染服務。渲染服務管理動畫和屏幕上組合的圖層。
當執行一段動畫的時候。這個過程會被切分爲六個階段,包含應用內的四個階段,與應用外的2個階段。當中應用內的階段例如如下:
  • 佈局(CPU):這是準備你的視圖/圖層的層級關係。以及設置圖層屬性(位置,背景色。邊框等等)的階段。
  • 顯示(CPU):這是圖層的寄宿圖片被繪製的階段。繪製有可能涉及你的-drawRect:-drawLayer:inContext:方法的調用路徑。
  • 準備(CPU):這是Core Animation準備發送動畫數據到渲染服務的階段。這同一時候也是Core Animation將要運行一些別的事務好比解碼動畫過程當中將要顯示的圖片的時間點。

  • 提交(CPU):這是最後的階段,Core Animation打包所有圖層和動畫屬性,而後經過IPC(內部處理通訊)發送到渲染服務進行顯示。
當數據被打包到渲染服務進程。會將其反序列化造成還有一個渲染樹。

使用這個渲染樹對動畫的每一幀作出例如如下工做:

  • 生成渲染樹:(CPU)對所有的圖層屬性計算中間值。設置OpenGL幾何形狀(紋理化的三角形)來運行渲染
  • 渲染(GPU):在屏幕上渲染可見的三角形

減小GPU圖層繪製的部分場景:
  • 太多的幾何結構 - 這發生在需要太多的三角板來作變換,以應對處理器的柵格化的時候。現代iOS設備的圖形芯片可以處理幾百萬個三角板。因此在Core Animation中幾何結構並不是GPU的瓶頸所在。但由於圖層在顯示以前經過IPC發送到渲染server的時候(圖層其實是由很是多小物體組成的特別重量級的對象),太多的圖層就會引發CPU的瓶頸。這就限制了一次展現的圖層個數(見本章興許「CPU相關操做」)。
  • 重繪 - 主要由重疊的半透明圖層引發。GPU的填充比率(用顏色填充像素的比率)是有限的,因此需要避免重繪(每一幀用相同的像素填充屢次)的發生。在現代iOS設備上,GPU都會應對重繪;即便是iPhone 3GS都可以處理高達2.5的重繪比率。並任然保持60幀率的渲染(這意味着你可以繪製一個半的整屏的冗餘信息,而不影響性能),並且新設備可以處理不少其它。
  • 離屏繪製 - 這發生在當不能直接在屏幕上繪製。並且必須繪製到離屏圖片的上下文中的時候。

    離屏繪製發生在基於CPU或者是GPU的渲染,或者是爲離屏圖片分配額外內存,以及切換繪製上下文,這些都會減小GPU性能。對於特定圖層效果的使用,比方圓角,圖層遮罩。陰影或者是圖層光柵化都會強制Core Animation提早渲染圖層的離屏繪製。

    但這不意味着你需要避免使用這些效果,僅僅是要明確這會帶來性能的負面影響。

  • 過大的圖片 - 假設視圖繪製超出GPU支持的2048x2048或者4096x4096尺寸的紋理,就必需要用CPU在圖層每次顯示以前對圖片預處理,相同也會減小性能。

減小CPU圖層繪製的部分場景:
  • 佈局計算 - 假設你的視圖層級過於複雜,當視圖呈現或者改動的時候,計算圖層幀率就會消耗一部分時間。特別是使用iOS6的本身主動佈局機制尤其明顯。它應該是比老版的本身主動調整邏輯增強了CPU的工做。
  • 視圖惰性載入 - iOS僅僅會當視圖控制器的視圖顯示到屏幕上時纔會載入它。

    這對內存使用和程序啓動時間很是有優勢,但是當呈現到屏幕上以前,按下button致使的不少工做都會不能被及時響應。比方控制器從數據庫中獲取數據,或者視圖從一個nib文件裏載入,或者涉及IO的圖片顯示(見興許「IO相關操做」)。都會比CPU正常操做慢得多。

  • Core Graphics繪製 - 假設對視圖實現了-drawRect:方法,或者CALayerDelegate-drawLayer:inContext:方法,那麼在繪製不論什麼東西以前都會產生一個巨大的性能開銷。爲了支持對圖層內容的隨意繪製,Core Animation必須建立一個內存中等大小的寄宿圖片。而後一旦繪製結束以後,必須把圖片數據經過IPC傳到渲染server。在此基礎上,Core Graphics繪製就會變得十分緩慢。因此在一個對性能十分挑剔的場景下這樣作十分很差。
  • 解壓圖片 - PNG或者JPEG壓縮以後的圖片文件會比同質量的位圖小得多。但是在圖片繪製到屏幕上以前,必須把它擴展成完整的未解壓的尺寸(一般等同於圖片寬 x 長 x 4個字節)。

    爲了節省內存。iOS一般直到真正繪製的時候纔去解碼圖片(14章「圖片IO」會更具體討論)。

    依據你載入圖片的方式,第一次對圖層內容賦值的時候(直接或者間接使用UIImageView)或者把它繪製到Core Graphics中。都需要對它解壓。這種話,對於一個較大的圖片,都會佔用必定的時間。

二、Instruments實現App性能優化,操做順序一般例如如下:
  • 加入優化工具
  • 選擇福選項。設置感興趣的數據
  • 對照測試得結果
Efficient Drawing(高效畫圖)

一、軟件繪製
軟件畫圖意爲不借助GPU的圖形繪製。在iOS中一般就是由Core Graphics來實現。但其對照Core Animation和OpenGL,Core Graphics要慢很多,而且也十分消耗內存。
軟件畫圖不只效率低,還會消耗可觀的內存。 CALayer 僅僅需要一些與本身相關的內存:僅僅有它的寄宿圖會消耗必定的內存空間。即便直接賦給 contents 屬性一張圖片,也不需要添加額外的照片存儲大小。假設一樣的一張圖片被多個圖層做爲 contents 屬性,那麼他們將會共用同一塊內存,而不是複製內存塊。

但是一旦你實現了 CALayerDelegate 協議中的 -drawLayer:inContext: 方法或者 UIView 中的 -drawRect: 方法(事實上就是前者的包裝方法),圖層就建立了一個繪製上下文,這個上下文需要的大小的內存可從這個算式得出:圖層寬*圖層高*4字節。寬高的單位均爲像素。對於一個在Retina iPad上的全屏圖層來講。這個內存量就是 2048*1526*4字節,至關於12MB內存,圖層每次重繪的時候都需要又一次抹掉內存而後又一次分配。

軟件畫圖的代價昂貴,除非絕對必要。你應該避免重繪你的視圖。

提升繪製性能的祕訣就在於儘可能避免去繪製。



二、矢量圖形

咱們用Core Graphics來畫圖的一個一般緣由就是僅僅是用圖片或是圖層效果不能輕易地繪製出矢量圖形。矢量畫圖包括一下這些:

  • 隨意多邊形(不不過一個矩形)
  • 斜線或曲線
  • 文本
  • 漸變
文章中實現了例如如下效果的demo:


事實上現思路就是每當有touch event發生,則向UIBezierPath中加入一條直線。但在對於屏幕中每當有一個touch event事件發生,意味着整個屏幕都要又一次繪製一遍,當需要又一次繪製的內容愈來愈多,則會引發幀率的降低。

這時候咱們可以經過髒矩陣來對這個問題進行優化。


三、髒矩形
髒矩形是一個能制定又一次繪製區域的機制。

在程序中則是經過用setNeedDispalyInRect來替代setNeedDispaly方法來實現繪製詳細的區域,詳細實現見文章。


四、異步繪製
UIKit的單線程天性意味着寄宿圖一般要在主線程上更新,這意味着繪製會打斷用戶交互,甚至讓整個app看起來處於無響應狀態。咱們對此無能爲力,但是假設能避免用戶等待繪製完畢就好多了。

針對這個問題,core Animation提供了一下兩種方案來實現異步繪製,提升界面的響應效率:
  • CATiledLayer(詳細實現可見第六章)
  • drawsAsynchronously(????)



Image IO(圖像IO)——研究怎樣優化從閃存或者網絡中載入和顯示圖片

一、載入與潛伏
畫圖實際消耗的時間一般並不是影響性能的因素,而且若把圖片直接存儲在內存,會損耗大量的資源, 因此需要在應用執行的時候週期性地載入和卸載圖片。
圖片文件的載入速度同一時候受到CPU及IO(輸入/輸出)延遲的影響。

iOS設備中的閃存已經比傳統硬盤快很是多了。但仍然比RAM慢將近200倍左右,這就需要慎重地管理載入。以免延遲。

有時候圖片也需要從遠程網絡鏈接中下載,這將會比從磁盤載入要消耗不少其它的時間,甚至可能由於鏈接問題而載入失敗(在幾秒鐘嘗試以後)。你不能在主線程中載入網絡,並在屏幕凍結期間指望用戶去等待它。因此需要後臺線程。


二、異步線程載入
由於圖片的載入是十分耗時間的,若把該操做放置在主線程中運行會減小CPU的利用率甚至拖慢幀率。可以經過GCD或者NSOperationQueue來實現異步載入最後再在主線程中同步發起渲染就能夠。

三、延遲解壓
一旦圖片文件被載入使用。就必須要通過解碼(解壓)的過程,解碼過程是一個至關複雜的任務。耗時長也佔大量的內存。
對於PNG:載入相對長。文件相對更大,但解碼比較快。
對於JPEG:載入快,圖片小,但解碼算法複雜耗時長。

由於iOS系統會讓載入完畢的圖片不會立刻解壓,而是到需要用的時刻才正式解壓。因此會影響性能。

  • iOS系統提供下面三種方式來實現繞過延遲解壓的機制
    • imageName方法是能避免延遲載入。而且該方法在載入後會立刻解壓,但僅僅相應用資源束有效。
    • 將載入圖片設置爲圖層內容。如UIImageView的iamge屬性。但這需要在主線程運行。因此不會對性能有大的提高
    • 使用ImageIO框架

四、使用CATiledLayer實現異步載入和顯示大型圖片
略。


五、分辨率交換
略。


六、使用imageNamed實現緩存
imageName方法是能避免延遲載入,而且該方法在載入後會立刻解壓,但僅僅相應用資源束有效。因此網絡圖片無效。
以前咱們提到使用 [UIImage imageNamed:] 載入圖片有個優勢在於可以立馬解壓圖片而不用等到繪製的時候。但是 [UIImage imageNamed:] 方法有還有一個很顯著的優勢:它在內存中本身主動緩存瞭解壓後的圖片。即便你本身沒有保留對它的不論什麼引用。

因此也要注意不能用於載入大圖片,否則會佔用大量的內存資源。


  • 對於下面場景不能使用imageName。需要本身實現緩存機制:
    • [UIImage imageNamed:]方法只適用於在應用程序資源束文件夾下的圖片,但是大多數應用的不少圖片都要從網絡或者是用戶的相機中獲取,因此 [UIImage imageNamed:]就無法用了。
    • [UIImage imageNamed:]緩存用來存儲應用界面的圖片(button,背景等等)。假設對比片這樣的大圖也用這樣的緩存,那麼iOS系統就很是可能會移除這些圖片來節省內存。

      那麼在切換頁面時性能就會降低,因爲這些圖片都需要又一次載入。對傳送器的圖片使用一個單獨的緩存機制就行把它和應用圖片的生命週期解耦。

    • [UIImage imageNamed:]緩存機制並不是公開的。因此你不能很是好地控制它。好比,你無法作到檢測圖片是否在載入以前就作了緩存。不能夠設置緩存大小,當圖片無用的時候也不能把它從緩存中移除。

七、本身定義緩存

  • 若需要實現本身的緩存機制。一般得從下面四個方面進行考慮:
    • 選擇一個合適的緩存鍵 - 緩存鍵用來作圖片的惟一標識。

      假設實時建立圖片,一般不太好生成一個字符串來區分別的圖片。

      在咱們的圖片傳送帶樣例中就很是easy,咱們可以用圖片的文件名稱或者表格索引。

    • 提早緩存 - 假設生成和載入數據的代價很是大。你可能想當第一次需要用到的時候再去載入和緩存。

      提早載入的邏輯是應用內在就有的。但是在咱們的樣例中,這也很是好實現,因爲對於一個給定的位置和滾動方向。咱們就可以精確地推斷出哪一張圖片將會出現。

    • 緩存失效 - 假設圖片文件發生了變化。如何才幹通知到緩存更新呢?這是個很是困難的問題(就像菲爾 卡爾頓提到的),但是幸運的是當從程序資源載入靜態圖片的時候並不需要考慮這些。對用戶提供的圖片來講(可能會被改動或者覆蓋),一個比較好的方式就是當圖片緩存的時候打上一個時間戳以便當文件更新的時候做比較。
    • 緩存回收 - 當內存不夠的時候,如何推斷哪些緩存需要清空呢?這就需要到你寫一個合適的算法了。

      幸運的是,對緩存回收的問題。蘋果提供了一個叫作NSCache通用的解決方式



八、NSCache
NSCache和NSDictionary相似。都是直接經過鍵值進行訪問,但不一樣的是,NSCache所持有的對象在內存不足的時候。會本身主動將其釋放。
  • 固然開發人員可以經過下面設置來粗顆粒度地進行緩存管理的約束
    • -setCountLimit:方法設置緩存大小
    • -setObject:forKey:cost:來對每個存儲的對象指定消耗的值來提供一些暗示
    • -setTotalCostLimit:方法來指定全體緩存的尺寸

九、文件格式與載入性能
略。

Layer Performance(圖層性能)


一、隱形繪製
  • 寄宿層可以經過下面方式顯示繪製
    • Core Graphics
    • 給contents屬性賦值圖片
    • 在屏幕外事先繪製CGContext

  • 當發生下面場景會觸發隱式繪製
    • 使用特性的圖層屬性
    • 特定的視圖
    • 特定視圖的子類

二、文本
CATextLayer與UILable都是直接將文本繪製在圖層的寄宿層內,因此要避免頻繁的修改,若該文本需要頻繁修改,可以先將其放在一個子圖層上,經過contentMode來等比例縮放寄宿層。


三、光柵化
咱們提到了 CALayer shouldRasterize 屬性(光柵化)。它可以解決重疊透明圖層的混合失靈問題。
啓用 shouldRasterize 屬性會將圖層繪製到一個屏幕以外的圖像。而後這個圖像將會被緩存起來並繪製到實際圖層的 contents 和子圖層。

假設有很是多的子圖層或者有複雜的效果應用,這樣作就會比重繪所有事務的所有幀划得來得多。

但是光柵化原始圖像需要時間。而且還會消耗額外的內存。

當咱們使用得當時,光柵化可以提供很是大的性能優點(如你在第12章所見),但是必定要避免做用在內容不斷變更的圖層上,不然它緩存方面的優勢就會消失。而且會讓性能變的更糟。
爲了檢測你是否正確地使用了光柵化方式,用Instrument查看一下Color Hits Green和Misses Red項目。是否已光柵化圖像被頻繁地刷新(這樣就說明圖層並不是光柵化的好選擇,或則你無心間觸發了沒必要要的改變致使了重繪行爲)。
總結:會佔用較多內存,要避免反覆繪製。因此一旦應用要儘可能下降又一次繪製,而多利用快照緩存。

四、離屏渲染
  • 當圖層的下面屬性被改動會觸發離屏渲染
    • 圓角(當和maskToBounds一塊兒使用時)
    • masks(圖層蒙板)
    • shadows(陰影)
    • shouldRasterize(光柵化)
    • edge antialiasing(抗鋸齒)
    • group opacity(不透明)
    • 漸變

屏幕外渲染和咱們啓用光柵化時類似。除了它並無像光柵化圖層那麼消耗大。子圖層並無被影響到,而且結果也沒有被緩存,因此不會有長期的內存佔用。但是,假設太多圖層在屏幕外渲染依舊會影響到性能
對於那些需要動畫而且要在屏幕外渲染的圖層來講。你可以用 CAShapeLayer contentsCenter 或者 shadowPath 來得到相同的表現而且較少地影響到性能。

五、混合和過分繪製
開發人員應該儘可能下降重疊圖層的反覆渲染,因爲對於用戶看來某些遮擋的圖層的內容是可有可無的,但渲染就會消耗資源。因此無論不論什麼場景都建議例如如下操做:
  • 給視圖的backgroundColor屬性設置一個固定的,不透明的顏色
  • 設置opaque屬性爲YES
  • 明智地使用shouldRasterize屬性,可以將一個固定的圖層體系摺疊成單張圖片,這樣就不需要每一幀又一次合成了,也就不會有因爲子圖層之間的混合和過分繪製的性能問題了。
固然光柵化是是詳細場景二選擇使用,否則也會引入別的性能問題,如佔用大量內存。


六、下降圖層數量
初始化圖層,處理圖層,打包經過IPC發給渲染引擎,轉化成OpenGL幾何圖形,這些是一個圖層的大體資源開銷。其實,一次性能夠在屏幕上顯示的最大圖層數量也是有限的。

確切的限制數量取決於iOS設備。圖層類型。圖層內容和屬性等。

但是總得說來可以容納上百或上千個,如下咱們將演示即便圖層自己並無作什麼也會遇到的性能問題。


七、對象回收
處理巨大數量的類似視圖或圖層時另外一個技巧就是回收他們。對象回收在iOS頗爲常見。 UITableView UICollectionView 都實用到, MKMapView 中的動畫pin碼也實用到,還有其它很是多樣例。




Q&A:
  • Q:圖層沒有寄宿層,是否等於沒法顯示內容?(寄宿層)
    • A:不是,還有經過矢量圖繪製的方式來實現圖形呈現。如通用的現在應該就是經過算來來繪製矢量圖的,僅僅有需要顯示圖片或者調用core graphics的時候纔會生成寄宿層。因此若非必要不要實現draw方法。否則系統會默認加入一個寄宿層。

  • Q:組透明的點顏色計算公式?(視覺效果)
    • A:若某子view是透明的。那麼它的顏色公式爲:child_color*alpha + super_color*(1-alpha)。

  • Q:3D效果與共享滅點的詳細操做?(變換)
    • A:在作3D效果時要儘可能將所有圖形的滅點設置在屏幕的中心。因此建議先在屏幕的中心建立圖像。而後經過transform的形式來移動圖層。那麼就能保證滅點在屏幕中心。
  • Q:3D變化計算?(變換)
    • A:提供了平移、旋轉、縮放,但每次操做都是基於二維的,因此注意當前的參考座標系,剩下的計算與二維同樣。
  • Q:立方體的光亮與陰影原理?(變換)
    • A:經過GLK庫的函數計算垂直,並加入陰影層。
  • Q:3D點擊事件處理?(變換)
    • A:在3D圖層中。因爲一個點擊的點,實際上可能會穿過兩個圖層的點,這時事件攔截的順序由subviews數組的順序認爲,也就是誰最靠近用戶視覺,誰有限響應。
  • Q:常規的界面繪製是經過矢量繪製仍是寄宿圖繪製實現?(專用圖層)
    • A:常規界面是矢量繪製完畢的。
  • Q:平面化3d層級結構的意思?(專用圖層)
    • A:
  • Q:CATiledLayer解決大圖載入(專用圖層)
    • A:

0
0
 
 

相關文章
相關標籤/搜索