關於Core Animation
Core Animation是iOS與OS X平臺上負責圖形渲染與動畫的基礎設施。Core Animation能夠動畫視圖和其餘的可視元素。Core Animation爲你完成了實現動畫所需的大部分繪幀工做。你只需在配置少許的動畫參數(如開始點位置和結束點位置)就可啓動Core Animation。Core Animation將大部分實際的繪圖任務交給了圖形硬件處理,圖形硬件會加速圖形渲染的速度。這種自動化的圖形加速讓動畫具備更高的幀率且更加平滑,但 這並不會增長CPU的負擔而致使影響你應用的運行速度。
若是你正在開發一個iOS應用,你就已經使用到了Core Animation;若是你開發的是OS X應用,你僅需小小的付出就能夠利用Core Animation的強大功能。以下圖,Core Animation位於AppKit和UIKit的底層。它被緊密的集成到了Cocoa和Cocoa Touch視圖工做流中。雖然被緊密的集成,Core Animation也存在擴展功能的接口,這些接口暴露給了應用的視圖。使用這些接口能讓你更細粒度地控制應用中的動畫。
簡介
你可能從不須要直接使用Core Animation,可是當你使用Core Animation,你應該瞭解Core Animation是你app基礎設施中的一部分。
Core Animation管理着你的應用內容
Core Animation自身並非一個繪圖系統。它 只是一個負責在硬件上合成和操縱應用內容的基礎構件。Core Animation的核心是圖層對象,圖層對象用於管理和操控你的應用內容。圖層將捕獲的內容放到一副位圖中,圖形硬件可以很是容易的操控你的位圖。在大 部分應用中,圖層被做爲一種管理視圖內容的方式,可是你也能夠建立標準的圖層,這取決於你自身的須要。
更改圖層屬性會產生動畫
你使用Core Animation建立的大部分動畫都包含對圖層屬性的更改。像視圖同樣,圖層對象也具備邊框矩形、座標原點、尺寸、不透明度、變換矩陣以及許多其餘面向 可視的屬性(如backgroundColor)。大部分這些屬性的值發生了變化都將會觸發隱式動畫被建立。隱式動畫是一種從舊屬性值動畫到新屬性值的動 畫形式。若是須要全面掌控動畫行爲,你能夠考慮使用顯式動畫這些屬性。
有組織的圖層層級
有組織的圖層之間存在着父子關係。圖層的組織會影響到圖層的可見內容。可見內容的管理與視圖的管理方法類似。附到視圖上的圖層集合的層級鏡像對應的視圖層級。你能夠將獨立圖層添加到圖層的層級以擴充你的視圖的可視內容。
使用動做對象改變圖層的默認行爲
經過動做對象能夠作到隱式的圖層動畫。動做對象是 實現了一個預約義接口的常規對象。Core Animation使用動做對象實現與圖層關聯的常規的默認動畫集合。你能夠建立屬於你本身的動做對象,以實現自定義的動畫或者實現其餘行爲類型,而後你 將動做對象賦值給圖層的某一屬性。當屬性發生變化,Core Animation檢索你的動做對象並告訴動做對象執行對應的動做。
如何使用該文檔
該文檔爲那些須要更全面的控制動畫效果或打算利用圖層提高繪圖性能的開發者。該文檔也介紹了iOS和OS X對圖層和視圖的合成。圖層和視圖的合成在iOS和OS X平臺上是不一樣的,理解這些不一樣對於建立高效的動畫相當重要。
預備知識
你應該瞭解你的目標平臺的視圖架構,以及熟悉如何建立基於視圖的動畫。若是你還未到該階段,請閱讀如下兩篇文檔:
對於OS X應用開發,你應該理解《
視圖編程指南》中關於視圖架構的描述。
Core Animation基礎
Core Animation爲動畫視圖和其餘可視元素提供了一個通用的系統。Core Animation並非視圖的替代品,相反,它是一種和視圖相集成的技術。因爲位圖能夠直接由圖形硬件直接操控,經過將視圖的內容緩存到位圖中, 該技術可得到更優的性能且支持動畫視圖內容。除了緩存視圖內容,Core Animation也定義了指定任意可視內容,而後將內容和視圖集成,最後動畫視圖和其餘可視元素的方式。
使用Core Animation讓視圖和可視對象的變化能以動畫的形式呈現。大部分變化都與可視對象屬性的更改相關。好比Core Animation能讓視圖的位置、尺寸或者透明度的變化以動畫的形式呈現。當你更改了這些屬性的值, Core Animation在當前屬性值和最新指定的屬性值之間進行動畫。你通常不須要像卡通片那樣,完成每秒60次的視圖內容替換。相反,你應該利用Core Animation提供的移動視圖、淡入淡出視圖、對視圖應用任意的變換、改變視圖的其餘可視屬性的方式完成動畫 。
圖層是繪圖與動畫的基礎
圖層對象是組織在三維空間的二維平面。它是使用Core Animation執行任何操做的核心構件。和視圖同樣,圖層的可管理信息包括幾何結構、內容、可視屬性;不一樣於視圖,
圖層沒有定義它本身的外觀,圖層僅管理周圍位圖的狀態信息。位圖能夠是視圖的繪圖結果或者一張圖片。所以主要的圖層被認爲是模型對象,由於它們主要是用於管理數據。此概念務必記住,由於它影響到動畫的行爲。
基於圖層的繪圖模型
大部分圖層不作實際的繪圖操做。相反,圖層捕獲應用的內容並緩存它們到位圖中。位圖有時也被稱爲儲備(backing store)。當你隨後改變了一個圖層的屬性值,你作的全部只是改變了與圖層對象相關聯的狀態信息。當你的更改觸發了一個動畫,Core Animation傳遞圖層的位圖和圖層的狀態給圖形處理硬件。圖形處理器所作的工做是使用得到的信息渲染位圖,如圖1-1所示,用圖形處理硬件操縱位圖 要比圖形處理軟件能得到更高的動畫效果。
由於操縱的是靜態的位圖,基於圖層的繪圖和基於視圖的繪圖在技術上有明顯的不一樣。對基於視圖的繪圖,對視圖的改變常常會觸發調用視圖的 drawRect:方法以重繪視圖內容。可是此種方式的代價相對較高,由於它是CPU在主線程上的操做。Core Animation經過儘量的使用圖形硬件操縱緩存後的位圖來避免了這種開銷,從而完成相同或類似的效果。
雖然Core Animation儘量的使用緩存後的內容,但也必須提供初始內容並不時地更新它。
基於圖層的動畫
圖層的數據和狀態信息是從圖層內容的可視呈現中被分離了出來的。這種分離性給了Core Animation介入以及從舊的屬性值動畫到新的屬性值的機會。例如改變一個圖層的position屬性會引發Core Animation將圖層從當前的位置移動到新的具體位置。對其餘屬性作類似的改變將引發適當的動畫效果。圖1-2展現了一些能夠執行在圖層上的動畫類 型。
圖1-2 可在圖層上執行的動畫類型
在動畫運行期間,Core Animation使用硬件幫你完成每一幀的繪製工做。你只須要指定動畫的開始點和結束點,剩下的交由Core Animation完成。如若須要,你也能夠指定自定義時間信息和動畫參數,若是你沒有指定, Core Animation會提供適當的默認值。
圖層對象定義了本身的幾何結構
圖層的其中一項任務就是管理自身內容的可視幾何。可視幾何包含關於圖層內容邊界、在屏幕上的位置,是否圖層已被旋轉、縮放,或應用了某種變換。 與視圖相似,一個圖層有一個frame和bound屬性,你可使用這兩個屬性來定位圖層和它的內容。圖層也有一些視圖所沒有的屬性,好比anchor屬 性,任何變換操做都是圍繞該點運轉的(能夠理解爲一個按在圖層上的圖釘)。圖層的某些幾何概念的指定方式與視圖信息的指定方式也有不一樣。
圖層使用兩種類型的座標系統
圖層利用基於點的座標系統和單位座標系統指定內容的佈局。座標系統的選擇依賴於被傳達的信息類型。當指定的值是直接映射到屏幕或相對於其餘圖層 的座標,好比圖層的position屬性,則使用基於點的座標系統。當指定的值是相對於一些其餘的值,與屏幕座標不相關聯,則使用單位座標。好比圖層的 anchorPoint屬性,anchorPoint屬性指定了相對於圖層邊界的一個點。anchorPoint屬性能夠更改。
基於點的座標最經常使用於指定圖層的尺寸和位置。可經過圖層的bounds和postion屬性設定圖層的尺寸和位置。bound定義了圖層自身的 座標系統幷包含圖層在屏幕上的尺寸。position屬性定義了圖層相對於父座標系統的位置。雖然圖層有一個frame屬性,該屬性其實是從 bounds和position屬性派生而來,極少被使用。
圖層的bounds和frame矩形的方向始終與底層平臺的默認方向相匹配。圖1-3顯示了iOS和OS X平臺上邊界矩形的默認方向。在iOS中,默認狀況下邊界矩形的原點在圖層的左上角。而OS X上邊界矩形的原點則在左下角。若是你在iOS和OS X版本的app之間共享Core Animation代碼,必定要對此種狀況作區別對待。
圖1-3 iOS與OS X平臺默認的圖層幾何結構
注意到圖1-3中position屬性被定位在圖層的中間位置。position屬性的變化參照圖層的anchorPoint屬性。
錨點是使用單位座標系統的屬性之一。Core Animation中使用單位座標表示的屬性值可能會由於圖層的尺寸變化而發生改變。你能夠把單位座標當作是總數的百分比。在單位座標系統空間中每個坐 標的取值範圍在0.0和1.0之間。好比說,沿着x軸,左側是0.0,右側是1.0.沿着y軸,單位座標值方向的不一樣依賴於具體的平臺。如圖1-4所示。
圖1-4 iOS和OS X平臺默認的單位座標系統
注意:直到OS X 10.8纔出現了geometryFlipped屬性,該屬性能夠改變默認圖層y座標的方向。當翻轉變換被調用時,使用該屬性來調整圖層的方向有的時候是 必需的。若是父視圖使用了翻轉變換,它的子視圖內容(以及它對應的圖層)將常常被顛倒。在這種狀況下,設置子圖層的geometryFlipped屬性爲 YES是一種修正該問題最簡單的方法。在OS X 10.8及以上版本,AppKit負責管理該屬性,你不該該更改它。對於iOS app,不推薦使用geometryFlipped屬性。
全部的座標值,不管是點仍是單位座標都以浮點數指定。使用浮點數容許你更精確的指定可能落在整數座標值之間的點。特別是打印或向retina屏幕繪圖,浮點值都會很方便。浮點值容許你忽略底層設備的分辨率,而你只須要指定值的精度。
錨點影響幾何結構的操做
圖層的幾何操是相對於圖層的錨點進行的,anchorPoint屬性能夠訪問圖層的錨點值。當改變圖層的postion和transform屬性值,錨點的影響就很明顯。position屬性是相對於圖層的錨點被指定。而且任何你對圖層陰影的變換操做也是相對於錨點。
圖1-5說明了改變錨點對圖層position屬性的影響。儘管圖層沒有在它的父邊界內移動,將錨點從中心點移動到圖層邊界的原點將改變position屬性值。
圖1-5 錨點是如何影響圖層的position屬性
圖1-6顯示了錨點的變化是如何影響到應用在圖層上的變換。當你對圖層應用了一個旋轉變換,圖層將圍繞中心點旋轉。由於默認狀況下,錨點被設定在圖層的中心位置。通常建立這類旋轉行爲正是你所指望的。然而若是你改變了錨點值,旋轉的結果也會發生變化。
圖1-6 錨點是如何影響圖層的變換
圖層可在三維空間中操做
圖層有兩個操控圖層和內容的變換矩陣,transform和sublayerTransform屬性。CALayer的transform屬性 用來指定應用到圖層和它內嵌的子層上的變換。一般當你想更改圖層自己則使用該屬性。比方說,你可能使用該屬性縮放或旋轉圖層,或是臨時的改變圖層的位置。 sublayerTransform屬性定義了僅應用在子層上的變換以及給場景內容添加透視效果。
變換行爲由多個座標肯定,這些座標經過一個數字矩陣來獲取,獲取的座標結果是原始點被變換後的版本。由於Core Animation的值可在三維空間中指定,每一個座標點有四個值,這四個值須要和一個4*4的矩陣相乘。
如圖1-7所示。在Core Animation中,圖中的變換由CATransform3D類型表示。幸運的是,你不須要直接更改這個結構中的域值來執行標準變換。Core Animation爲建立縮放、平移、旋轉矩陣以及矩陣比較提供了綜合的函數集。除了使用函數操縱變換。Core Animation擴展了鍵值編碼以支持你使用鍵路徑更改一個變換操做。
圖1-7 使用矩陣數學轉換一個座標
圖1-8顯示了對一些常見的變換矩的配置。任何座標與單位矩陣相乘將返回徹底相同的座標。座標如何被更改徹底依賴於你變化的矩陣因子。好比,爲 了僅在X軸上平移,你只需對變換矩陣的tx因子應用一個非零值,並讓ty和tz值爲0。若是是旋轉,應用一個旋轉角度的正弦和餘弦值。
圖1-8 常見變換的矩陣配置
不一樣的圖層樹反映了不一樣的動畫狀態
使用Core Animation的app擁有三個圖層對象集合。每個圖層對象集合在呈現app內容上都扮演着不一樣的角色。
Ø模型圖層樹中的對象(或簡稱「圖層樹」)用的最多。在這個樹中的對象是模型對象,模型對象負責存儲全部動畫的目標值。不管什麼時候改變圖層的屬性值,你使用的始終是某一個模型對象。
Ø呈現樹中的對象包含全部運行中的動畫的瞬時值。圖層樹對象包含的是動畫的目標值,而呈現樹中的對象表明顯示在屏幕上動畫的當前值。你不該該更改這個樹中的對象。相反,你使用這些對象來讀取當前動畫的值,可能用於建立開始於這些值的新的動畫。
Ø在渲染樹中的對象執行實際的動畫,而且對Core Animation是不公開的。
每個圖層對象集合被組織在一個層次結構中,相似於app中的視圖。事實上,在一個全部視圖都支持圖層功能的app來講,每個樹的初始結構完 全與圖層的層次相匹配。一個app能夠添加另外的圖層對象,所以圖層與視圖是不相關聯的。能夠按照需求將圖層對象插入到指定的視圖層級中。你可能爲了優化 app內容的性能而選擇加入圖層對象而非視圖,緣由在於圖層的開銷要比視圖低。圖1-9展現了出如今一個簡單iOS app的圖層分解圖。在示例中窗口包含了一個內容視圖,內容視圖包含了一個按鈕視圖和兩個獨立的圖層對象。每個視圖擁有一個相對應的構成圖層層次的圖層 對象。
圖1-9 與窗口相關聯的圖層
在圖層樹中的每個對象,在渲染樹和呈現樹中也存在一個與之匹配的對象。如圖1-10所示。正如以前提到過的,app主要與圖層樹中的對象進行 交互,但可能有時會訪問呈現樹中的對象。具體地,訪問圖層樹中對象的presentationLayer屬性將返回一個在呈現樹中相對應的對象。你可能會 經過該對象獲取在動畫執行過程當中的某一時刻的屬性值。
圖1-10 窗口中的圖層樹
重要:只在動畫運行時訪問呈現樹中的對象。當動畫在進行中,呈現樹就包含了圖層顯示在屏幕上的那一刻的值。該行爲與圖層樹不一樣,圖層樹永遠只表示最終的目標值。
圖層不是視圖的替代品。所以沒法建立一個基於單一圖層對象的可視界面。圖層是視圖的基礎設施。具體地,圖層讓視圖的繪圖和動畫更簡單和高效,並 且能在繪圖和動畫時保持高幀率。然而許多事情圖層沒法作到。圖層不能處理事件、繪製內容,特別是在響應鏈中,或是作一些其餘的事情。所以,每一個app必須 有一個或多個視圖來處理這類交互。
在iOS中,每個視圖有一個相對應的圖層對象。但在OS X中,你必須決定哪個視圖擁有圖層。OS X 10.8以及以前的版本中,添加圖層到全部視圖上也許是有意義的。然而你沒必要這樣作,你仍能夠關閉圖層防止沒必要要以及無根據的開銷。
圖層在某種程度上減小了程序的內存開銷,圖層的這些優勢遠遠超出它的缺點。因此最好是在禁用圖層支持以前測試你app的性能。
當你的視圖支持圖層後,此時該視圖被稱爲layer-backed視圖。對於layer-backed視圖,系統負責建立底層的圖層對象,並保 持與視圖的同步。因此iOS視圖都是支持圖層的而且在OS X中的大部分視圖也是如此。可是在OS X中,你也能夠建立圖層託管(layer-hosting view)視圖,該視圖的圖層對象由你來提供。
注意:對於layer-backed視圖,建議只 操做視圖而不是圖層。iOS中視圖僅僅是對圖層對象的精簡包裝,因此任何你對圖層的操做一般都會正常工做。可是iOS和OS X平臺上操縱圖層而不是圖層可能不會取得預期的結果。該文檔會盡量的指出這些陷阱並提供一種方式讓你能夠與它們工做。
除了與視圖相關的圖層,你也能夠建立獨立的圖層對象。你能夠嵌入這些獨立圖層對象到任何其餘圖層對象中,包括與視圖相關的圖層。你通常使用圖層 對象做爲具體優化方法的一部分。好比說,若是你想使用相同的圖片在多個地方,你能夠只加載圖片一次,而後將圖片和多個獨立的圖層對象相關聯,最後添加這些 圖層對象到圖層樹中。每個圖層只會引用源圖片而不是嘗試在內存中建立自身對圖片的拷貝。