版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.09.21 |
前言
app中好的炫的動畫可以讓用戶耳目一新,為產品增色不少,關于動畫的實現我們可以用基本動畫、關鍵幀動畫、序列幀動畫以及基于CoreGraphic的動畫等等,接下來這幾篇我就介紹下我可以想到的幾種動畫繪制方法。具體Demo示例已開源到Github —— 刀客傳奇,感興趣的可以看我寫的另外幾篇。
1. 實現動畫方式深度解析(一) —— 播放GIF動畫(一)
2. 實現動畫方式深度解析(二) —— 播放GIF動畫之框架FLAnimatedImage的使用(二)
3. 實現動畫方式深度解析(三) —— 播放序列幀動畫(一)
4. 實現動畫方式深度解析(四) —— QuartzCore框架(一)
5. 實現動畫方式深度解析(五) —— QuartzCore框架之CoreAnimation(二)
Core Animation Basics
核心動畫提供了一個通用的系統,用于動畫化您的app視圖和其他視覺元素。 核心動畫不是您的app視圖的替代品。 相反,它是一種視圖集成的技術,可以為動畫內容提供更好的性能和支持。 通過將視圖的內容緩存到可以由圖形硬件直接操縱的位圖中來實現此行為。 在某些情況下,這種緩存行為可能需要您重新思考如何呈現和管理應用程序的內容,但大多數時候您使用Core Animation而無需知道它。 除了緩存視圖內容之外,Core Animation還定義了一種指定任意可視內容的方法,將該內容與視圖集成,并將其與其他所有內容一起動畫化。
您可以使用Core Animation來動畫更改應用程序的視圖和視覺對象。 大多數更改涉及修改視覺對象的屬性。 例如,您可以使用Core Animation來動態更改視圖的位置,大小或不透明度。 當您進行這樣的更改時,核心動畫將在當前的屬性值和您指定的新值之間動畫化。 通常不會使用Core Animation來代替視圖的內容,每秒60次,如漫畫。 相反,您可以使用Core Animation將視圖的內容移動到屏幕上,將內容淡入或淡出,對視圖應用任意圖形轉換,或更改視圖的其他視覺屬性。
Layers Provide the Basis for Drawing and Animations
layer對象是組織在3D空間中的2D表面,并且是您使用Core Animation執行的所有操作的核心。 像視圖一樣,layer管理有關其表面的幾何,內容和視覺屬性的信息。 不同于視圖,layer沒有定義自己的外觀。 layer層僅管理位圖周圍的狀態信息。 位圖本身可以是您自己指定的視圖或您指定的固定圖像的結果。 因此,您在應用程序中使用的main layer被認為是模型對象,因為它們主要管理數據。 這個概念很重要,因為它影響動畫的行為。
1. The Layer-Based Drawing Model - 基于Layer的繪畫模型
大多數圖層在您的應用程序中沒有實際繪制。 相反,一個圖層捕獲您的應用程序提供的內容,并將其緩存在位圖中,該位圖有時稱為后備存儲。 當您隨后更改圖層的屬性時,您所做的就是更改與圖層對象關聯的狀態信息。 當更改觸發動畫時,Core Animation會將圖層的位圖和狀態信息傳遞給圖形硬件,從而使用新信息渲染位圖的工作,如圖1-1所示。 在硬件中操作位圖產生比軟件更快的動畫。
因為它操縱一個靜態位圖,基于層的繪圖與更傳統的基于視圖的繪圖技術顯著不同。 使用基于視圖的繪圖,對視圖本身的更改通常會導致調用視圖的drawRect:方法以使用新參數重繪內容。 但是以這種方式繪制是昂貴的,因為它是使用主線程上的CPU完成的。 Core Animation可以通過在硬件中操作緩存的位圖來實現相同或相似的效果,從而避免這種消耗。
雖然Core Animation盡可能使用緩存的內容,但您的應用仍然必須提供初始內容并時時更新。 您的應用程序有幾種方式為圖層對象提供內容,這些內容在提供圖層的內容中有詳細描述 Providing a Layer’s Contents. 。
2. Layer-Based Animations - 基于layer的動畫
層對象的數據和狀態信息與屏幕上該層內容的視覺呈現分離。 這種去耦使得核心動畫成為一種插入自己的方式,并將變化從舊的狀態值轉換為新的狀態值。 例如,更改圖層的position屬性會導致Core Animation將圖層從當前位置移動到新指定的位置。 與其他屬性類似的更改會導致適當的動畫。 下圖顯示了您可以在圖層上執行的一些動畫類型。 有關觸發動畫的圖層屬性列表,請參閱動畫屬性 Animatable Properties。
在動畫過程中,Core Animation可以在硬件中為您提供所有的逐幀繪圖。 所有你需要做的是指定動畫的開始和結束點,并讓核心動畫做其余的。 您還可以根據需要指定自定義定時信息和動畫參數; 但是,如果沒有,Core Animation提供了合適的默認值。
有關如何啟動動畫和配置動畫參數的更多信息,請參閱動畫圖層內容 Animating Layer Content。
Layer Objects Define Their Own Geometry - 定義自己幾何的層對象
layer的任務之一是管理其內容的視覺幾何。 視覺幾何包含關于該內容的界限,其在屏幕上的位置以及該layer是以任何方式旋轉,縮放或變換的信息。 像視圖一樣,圖層layer具有框架和邊框,您可以使用它們來定位圖層及其內容。 圖層還具有視圖沒有的其他屬性,例如錨點,其定義了操作發生的位置。 指定層幾何的某些方面的方式也不同于如何為視圖指定信息。
1. Layers Use Two Types of Coordinate Systems - 使用兩種不同坐標系統的圖層
圖層利用基于點的坐標系和單位坐標系來指定內容的位置。 使用哪個坐標系取決于正在傳達的信息的類型。 當指定直接映射到屏幕坐標的值時或者必須相對于另一層指定值時,使用基于點的坐標,例如對于圖層的position屬性。 當值不應與屏幕坐標相關時使用單位坐標,因為它相對于某個其他值。 例如,圖層的anchorPoint屬性指定了相對于圖層本身的邊界的點,這可以改變。
基于點的坐標最常見的用法是指定圖層的大小和位置,使用層的邊界和位置屬性。 邊界定義了圖層本身的坐標系,并包含圖層在屏幕上的大小。 position屬性定義了圖層相對于其父坐標系的位置。 盡管圖層具有frame屬性,但該屬性實際上是從邊界和位置屬性中的值導出的,并且使用的頻率較低。
層的邊界和框架矩形的方向總是與底層平臺的默認方向相匹配。 下圖顯示了iOS和OS上邊界矩形的默認方向。
上圖中要注意的一點是位置屬性位于圖層的中間。 該屬性是根據圖層的anchorPoint屬性中的值定義更改的幾個屬性之一。 錨點表示某些坐標來源的點,并在“錨點影響幾何操作 Anchor Points Affect Geometric Manipulations”中有更詳細的描述。
錨點是您使用單位坐標系指定的幾個屬性之一。 核心動畫使用單位坐標來表示當圖層的大小變化時其值可能會改變的屬性。 您可以將單位坐標視為指定總可能值的百分比。 單位坐標空間中的每個坐標的范圍都為0.0到1.0。 例如,沿x軸,左邊緣在坐標0.0處,右邊緣處于坐標1.0。 沿y軸,單位坐標值的方向取決于平臺,如下圖所示。
注意:直到OS X 10.8,geometryFlipped屬性才能在需要時更改圖層y軸的默認方向。 有時需要使用這個屬性來糾正一個層的方向。 例如,如果父視圖使用翻轉變換,則其子視圖(及其相應圖層)的內容通常會反轉。 在這種情況下,將子層的geometryFlipped屬性設置為YES可以解決問題。 在OS X 10.8及更高版本中,AppKit為您管理此屬性,您不應該修改它。 對于iOS應用程序,建議您不要使用geometryFlipped
屬性。
所有坐標值,無論它們是點還是單位坐標都被指定為浮點數。 使用浮點數允許您指定可能落在正常坐標值之間的精確位置。 使用浮點值是很方便的,特別是在打印期間或當繪制到Retina顯示屏上時,其中一個點可能由多個像素表示。 浮點值允許您忽略底層設備分辨率,并僅以所需精度指定值。
2. Anchor Points Affect Geometric Manipulations - 錨點影響幾何操縱
與圖層的錨點相關的幾何相關操作發生,您可以使用圖層的anchorPoint
屬性進行訪問。 當處理層的位置或變換屬性時,錨點的影響是最顯著的。 position屬性總是相對于圖層的錨點指定的,并且您應用于圖層的任何轉換也會相對于錨點發生。
下圖演示了如何將錨點從其默認值更改為不同的值會影響圖層的位置屬性。 即使圖層沒有在父層的邊界內移動,將錨點從圖層的中心移動到圖層的邊界起點也會改變position屬性的值。
下圖顯示了如何改變錨點影響應用于圖層的變換。 當您將旋轉變換應用于圖層時,旋轉將發生在錨點周圍。 因為默認情況下,錨點被設置在層的中間,所以通常會產生你期望的那種旋轉行為。 但是,如果更改錨點,旋轉結果將不同。
3. Layers Can Be Manipulated in Three Dimensions - 圖層可以在三維方向操作
每個層都有兩個變換矩陣,您可以使用它們來操縱圖層及其內容。 CALayer
的transform
屬性指定要應用于圖層及其嵌入的子圖層的轉換。 通常,當您要修改圖層本身時,您可以使用此屬性。 例如,您可以使用該屬性縮放或旋轉圖層或暫時更改其位置。 sublayerTransform屬性定義了僅適用于子層的附加轉換,最常用于向場景內容添加透視視覺效果。
通過將坐標值乘以數字矩陣來轉換操作,以獲得代表原始點的轉換版本的新坐標。 因為Core Animation值可以在三維中指定,所以每個坐標點都有四個必須乘以4×4矩陣的值,如下圖所示。 在Core Animation中,圖中的變換由CATransform3D類型表示。 幸運的是,您不必直接修改此結構的字段來執行標準轉換。 核心動畫提供了一套全面的函數用于創建縮放,轉換和旋轉矩陣以及進行矩陣比較。 除了使用函數操縱變換之外,Core Animation還擴展了鍵值編碼KVC支持,以允許您使用關鍵路徑修改變換。 有關可以修改的關鍵路徑的列表,請參閱CATransform3D密鑰路徑 CATransform3D Key Paths。
下圖顯示了您可以進行的一些更常見的轉換的矩陣配置。 通過identity變換乘以任何坐標返回完全相同的坐標。 對于其他變換,如何修改坐標完全取決于您更改的矩陣組件。 例如,要僅沿x軸轉換,您將為轉換矩陣的tx組件提供非零值,并將ty和tz值保留為0,對于旋轉,您將提供目標旋轉角度適當的正弦和余弦值。
有關用于創建和操作變換的功能的信息,請參閱Core Animation Function Reference
。
Layer Trees Reflect Different Aspects of the Animation State - layer樹反映動畫狀態的不同方面
使用Core Animation
的app有三組圖層layer對象,每套圖層對象在使您的app的內容出現在屏幕上方面具有不同的作用:
模型層樹
(或簡稱“層樹”)中的對象是您的應用程序與之最相互影響的對象。 此樹中的對象是存儲任何動畫的目標值的模型對象。 無論何時更改圖層的屬性,都可以使用其中一個對象。展示樹
中的對象包含任何正在運行的動畫的飛行中值。 而層樹對象包含動畫的目標值,而呈現樹中的對象會反映當前值在屏幕上顯示的值。 您不應該修改此樹中的對象。 而是使用這些對象來讀取當前的動畫值,也許是從這些值開始創建一個新的動畫。渲染樹
中的對象執行實際動畫,并且對Core Animation
是私有的。
每組圖層layer對象被組織成層次結構,如app中的視圖。 實際上,對于一個能夠為其所有視圖啟用圖層的app,每個樹的初始結構恰好匹配了視圖層次結構。 但是,app可以根據需要向層次結構中添加額外的圖層layer對象(即與視圖無關的圖層)。 您可以在不需要視圖所有開銷的內容的情況下優化app的性能。 下圖顯示了在一個簡單的iOS app中找到的圖層layer細分。 示例中的窗口包含一個內容視圖,該視圖本身包含一個按鈕視圖和兩個獨立的圖層對象。 每個視圖都有一個相應的圖層對象,它形成圖層層次結構的一部分。
對于圖層layer樹中的每個對象,展示樹和渲染樹中都有一個匹配的對象,如下圖所示。 如前所述,app主要使用圖層layer樹中的對象,但有時可以訪問展示樹中的對象。 具體來說,訪問layer樹中的對象的 presentationLayer屬性會返回呈現樹中的相應對象。 您可能希望訪問該對象以讀取動畫中間的屬性的當前值。
重要:只有當動畫在飛行中時,才能訪問展示樹中的對象。 當動畫正在進行時,展示樹包含當時在屏幕上顯示的圖層值。 此行為與圖層layer樹不同,圖層樹總是反映您代碼設置的最后一個值,相當于動畫的最終狀態。
The Relationship Between Layers and Views - 圖層和視圖的關系
圖層不能替代您的app的視圖,也就是說,您無法僅基于圖層layer對象創建可視界面。 layer層為您的view提供基礎部分。 具體來說,圖層使繪圖和動畫視圖的內容變得更加容易和有效,并且在執行此操作時保持較高的幀速率。 但是,還是有很多事情層layer是不能做的。 層layer不能處理事件、繪制內容、參與響應者鏈或做許多其他事情。 因此,每個app仍然必須有一個或多個視圖來處理這些交互。
在iOS中,每個視圖都由相應的圖層對象支持,但在OS X中,您必須確定哪些視圖應具有圖層。 在OS X v10.8
及更高版本中,將圖層添加到所有視圖可能是有意義的。 但是,您不需要這樣做,并且在開銷不合理和不必要的情況下仍可禁用層。 圖層確實會增加應用程序的內存開銷,但是它們的優勢往往超過劣勢,因此在禁用層支持之前,最好測試應用程序的性能。
為視圖啟用圖層支持時,可以創建所謂的支持層的視圖。 在層次支持的視圖中,系統負責創建底層圖層對象,并保持該圖層與視圖同步。 所有iOS視圖都是層次支持的,OS X中的大多數視圖也是如此。 但是,在OS X中,您還可以創建一個圖層托管視圖,這是您自己提供圖層對象的視圖。 對于層次托管視圖,AppKit采用手動管理層,不會修改它以響應視圖更改。
注意:對于層次支持的視圖,建議您盡可能操縱視圖,而不是圖層。 在iOS中,視圖只是圍繞層對象的薄包裝,因此您對圖層進行的任何操作通常都可以正常工作。 但是在iOS和OS X中都有這樣的情況,其中操縱圖層而不是視圖可能不會產生所需的結果。 盡可能地,本文件指出了這些陷阱,并嘗試提供方法來幫助您解決這些問題。
除了與視圖相關聯的圖層之外,還可以創建沒有相應視圖的圖層對象。 您可以將這些獨立圖層對象嵌入到應用程序中的任何其他圖層對象中,包括與視圖關聯的圖層對象。 通常使用獨立圖層對象作為特定優化路徑的一部分。 例如,如果要在多個地方使用相同的圖像,則可以加載圖像一次,并將其與多個獨立圖層對象相關聯,并將這些對象添加到圖層樹中。 每個層然后引用源圖像,而不是嘗試在內存中創建該圖像的自己的副本。
有關如何為應用程序的視圖啟用圖層支持的信息,請參閱Enabling Core Animation Support in Your App。 有關如何創建層對象層次結構的信息,以及有關何時可以這樣做的提示,請參閱Building a Layer Hierarchy。
后記
未完,待續~~~