實現(xiàn)動畫方式深度解析(六) —— Core Animation Basics(三)

版本記錄

版本號 時間
V1.0 2017.09.21

前言

app中好的炫的動畫可以讓用戶耳目一新,為產(chǎn)品增色不少,關(guān)于動畫的實現(xiàn)我們可以用基本動畫、關(guān)鍵幀動畫、序列幀動畫以及基于CoreGraphic的動畫等等,接下來這幾篇我就介紹下我可以想到的幾種動畫繪制方法。具體Demo示例已開源到Github —— 刀客傳奇,感興趣的可以看我寫的另外幾篇。
1. 實現(xiàn)動畫方式深度解析(一) —— 播放GIF動畫(一)
2. 實現(xiàn)動畫方式深度解析(二) —— 播放GIF動畫之框架FLAnimatedImage的使用(二)
3. 實現(xiàn)動畫方式深度解析(三) —— 播放序列幀動畫(一)
4. 實現(xiàn)動畫方式深度解析(四) —— QuartzCore框架(一)
5. 實現(xiàn)動畫方式深度解析(五) —— QuartzCore框架之CoreAnimation(二)

Core Animation Basics

核心動畫提供了一個通用的系統(tǒng),用于動畫化您的app視圖和其他視覺元素。 核心動畫不是您的app視圖的替代品。 相反,它是一種視圖集成的技術(shù),可以為動畫內(nèi)容提供更好的性能和支持。 通過將視圖的內(nèi)容緩存到可以由圖形硬件直接操縱的位圖中來實現(xiàn)此行為。 在某些情況下,這種緩存行為可能需要您重新思考如何呈現(xiàn)和管理應(yīng)用程序的內(nèi)容,但大多數(shù)時候您使用Core Animation而無需知道它。 除了緩存視圖內(nèi)容之外,Core Animation還定義了一種指定任意可視內(nèi)容的方法,將該內(nèi)容與視圖集成,并將其與其他所有內(nèi)容一起動畫化。

您可以使用Core Animation來動畫更改應(yīng)用程序的視圖和視覺對象。 大多數(shù)更改涉及修改視覺對象的屬性。 例如,您可以使用Core Animation來動態(tài)更改視圖的位置,大小或不透明度。 當(dāng)您進行這樣的更改時,核心動畫將在當(dāng)前的屬性值和您指定的新值之間動畫化。 通常不會使用Core Animation來代替視圖的內(nèi)容,每秒60次,如漫畫。 相反,您可以使用Core Animation將視圖的內(nèi)容移動到屏幕上,將內(nèi)容淡入或淡出,對視圖應(yīng)用任意圖形轉(zhuǎn)換,或更改視圖的其他視覺屬性。


Layers Provide the Basis for Drawing and Animations

layer對象是組織在3D空間中的2D表面,并且是您使用Core Animation執(zhí)行的所有操作的核心。 像視圖一樣,layer管理有關(guān)其表面的幾何,內(nèi)容和視覺屬性的信息。 不同于視圖,layer沒有定義自己的外觀。 layer層僅管理位圖周圍的狀態(tài)信息。 位圖本身可以是您自己指定的視圖或您指定的固定圖像的結(jié)果。 因此,您在應(yīng)用程序中使用的main layer被認為是模型對象,因為它們主要管理數(shù)據(jù)。 這個概念很重要,因為它影響動畫的行為。

1. The Layer-Based Drawing Model - 基于Layer的繪畫模型

大多數(shù)圖層在您的應(yīng)用程序中沒有實際繪制。 相反,一個圖層捕獲您的應(yīng)用程序提供的內(nèi)容,并將其緩存在位圖中,該位圖有時稱為后備存儲。 當(dāng)您隨后更改圖層的屬性時,您所做的就是更改與圖層對象關(guān)聯(lián)的狀態(tài)信息。 當(dāng)更改觸發(fā)動畫時,Core Animation會將圖層的位圖和狀態(tài)信息傳遞給圖形硬件,從而使用新信息渲染位圖的工作,如圖1-1所示。 在硬件中操作位圖產(chǎn)生比軟件更快的動畫。

因為它操縱一個靜態(tài)位圖,基于層的繪圖與更傳統(tǒng)的基于視圖的繪圖技術(shù)顯著不同。 使用基于視圖的繪圖,對視圖本身的更改通常會導(dǎo)致調(diào)用視圖的drawRect:方法以使用新參數(shù)重繪內(nèi)容。 但是以這種方式繪制是昂貴的,因為它是使用主線程上的CPU完成的。 Core Animation可以通過在硬件中操作緩存的位圖來實現(xiàn)相同或相似的效果,從而避免這種消耗。

雖然Core Animation盡可能使用緩存的內(nèi)容,但您的應(yīng)用仍然必須提供初始內(nèi)容并時時更新。 您的應(yīng)用程序有幾種方式為圖層對象提供內(nèi)容,這些內(nèi)容在提供圖層的內(nèi)容中有詳細描述 Providing a Layer’s Contents. 。

2. Layer-Based Animations - 基于layer的動畫

層對象的數(shù)據(jù)和狀態(tài)信息與屏幕上該層內(nèi)容的視覺呈現(xiàn)分離。 這種去耦使得核心動畫成為一種插入自己的方式,并將變化從舊的狀態(tài)值轉(zhuǎn)換為新的狀態(tài)值。 例如,更改圖層的position屬性會導(dǎo)致Core Animation將圖層從當(dāng)前位置移動到新指定的位置。 與其他屬性類似的更改會導(dǎo)致適當(dāng)?shù)膭赢嫛?下圖顯示了您可以在圖層上執(zhí)行的一些動畫類型。 有關(guān)觸發(fā)動畫的圖層屬性列表,請參閱動畫屬性 Animatable Properties。

在動畫過程中,Core Animation可以在硬件中為您提供所有的逐幀繪圖。 所有你需要做的是指定動畫的開始和結(jié)束點,并讓核心動畫做其余的。 您還可以根據(jù)需要指定自定義定時信息和動畫參數(shù); 但是,如果沒有,Core Animation提供了合適的默認值。

有關(guān)如何啟動動畫和配置動畫參數(shù)的更多信息,請參閱動畫圖層內(nèi)容 Animating Layer Content


Layer Objects Define Their Own Geometry - 定義自己幾何的層對象

layer的任務(wù)之一是管理其內(nèi)容的視覺幾何。 視覺幾何包含關(guān)于該內(nèi)容的界限,其在屏幕上的位置以及該layer是以任何方式旋轉(zhuǎn),縮放或變換的信息。 像視圖一樣,圖層layer具有框架和邊框,您可以使用它們來定位圖層及其內(nèi)容。 圖層還具有視圖沒有的其他屬性,例如錨點,其定義了操作發(fā)生的位置。 指定層幾何的某些方面的方式也不同于如何為視圖指定信息。

1. Layers Use Two Types of Coordinate Systems - 使用兩種不同坐標(biāo)系統(tǒng)的圖層

圖層利用基于點的坐標(biāo)系和單位坐標(biāo)系來指定內(nèi)容的位置。 使用哪個坐標(biāo)系取決于正在傳達的信息的類型。 當(dāng)指定直接映射到屏幕坐標(biāo)的值時或者必須相對于另一層指定值時,使用基于點的坐標(biāo),例如對于圖層的position屬性。 當(dāng)值不應(yīng)與屏幕坐標(biāo)相關(guān)時使用單位坐標(biāo),因為它相對于某個其他值。 例如,圖層的anchorPoint屬性指定了相對于圖層本身的邊界的點,這可以改變。

基于點的坐標(biāo)最常見的用法是指定圖層的大小和位置,使用層的邊界和位置屬性。 邊界定義了圖層本身的坐標(biāo)系,并包含圖層在屏幕上的大小。 position屬性定義了圖層相對于其父坐標(biāo)系的位置。 盡管圖層具有frame屬性,但該屬性實際上是從邊界和位置屬性中的值導(dǎo)出的,并且使用的頻率較低。

層的邊界和框架矩形的方向總是與底層平臺的默認方向相匹配。 下圖顯示了iOS和OS上邊界矩形的默認方向。

上圖中要注意的一點是位置屬性位于圖層的中間。 該屬性是根據(jù)圖層的anchorPoint屬性中的值定義更改的幾個屬性之一。 錨點表示某些坐標(biāo)來源的點,并在“錨點影響幾何操作 Anchor Points Affect Geometric Manipulations”中有更詳細的描述。

錨點是您使用單位坐標(biāo)系指定的幾個屬性之一。 核心動畫使用單位坐標(biāo)來表示當(dāng)圖層的大小變化時其值可能會改變的屬性。 您可以將單位坐標(biāo)視為指定總可能值的百分比。 單位坐標(biāo)空間中的每個坐標(biāo)的范圍都為0.0到1.0。 例如,沿x軸,左邊緣在坐標(biāo)0.0處,右邊緣處于坐標(biāo)1.0。 沿y軸,單位坐標(biāo)值的方向取決于平臺,如下圖所示。

注意:直到OS X 10.8,geometryFlipped屬性才能在需要時更改圖層y軸的默認方向。 有時需要使用這個屬性來糾正一個層的方向。 例如,如果父視圖使用翻轉(zhuǎn)變換,則其子視圖(及其相應(yīng)圖層)的內(nèi)容通常會反轉(zhuǎn)。 在這種情況下,將子層的geometryFlipped屬性設(shè)置為YES可以解決問題。 在OS X 10.8及更高版本中,AppKit為您管理此屬性,您不應(yīng)該修改它。 對于iOS應(yīng)用程序,建議您不要使用geometryFlipped屬性。

所有坐標(biāo)值,無論它們是點還是單位坐標(biāo)都被指定為浮點數(shù)。 使用浮點數(shù)允許您指定可能落在正常坐標(biāo)值之間的精確位置。 使用浮點值是很方便的,特別是在打印期間或當(dāng)繪制到Retina顯示屏上時,其中一個點可能由多個像素表示。 浮點值允許您忽略底層設(shè)備分辨率,并僅以所需精度指定值。

2. Anchor Points Affect Geometric Manipulations - 錨點影響幾何操縱

與圖層的錨點相關(guān)的幾何相關(guān)操作發(fā)生,您可以使用圖層的anchorPoint屬性進行訪問。 當(dāng)處理層的位置或變換屬性時,錨點的影響是最顯著的。 position屬性總是相對于圖層的錨點指定的,并且您應(yīng)用于圖層的任何轉(zhuǎn)換也會相對于錨點發(fā)生。

下圖演示了如何將錨點從其默認值更改為不同的值會影響圖層的位置屬性。 即使圖層沒有在父層的邊界內(nèi)移動,將錨點從圖層的中心移動到圖層的邊界起點也會改變position屬性的值。

下圖顯示了如何改變錨點影響應(yīng)用于圖層的變換。 當(dāng)您將旋轉(zhuǎn)變換應(yīng)用于圖層時,旋轉(zhuǎn)將發(fā)生在錨點周圍。 因為默認情況下,錨點被設(shè)置在層的中間,所以通常會產(chǎn)生你期望的那種旋轉(zhuǎn)行為。 但是,如果更改錨點,旋轉(zhuǎn)結(jié)果將不同。

3. Layers Can Be Manipulated in Three Dimensions - 圖層可以在三維方向操作

每個層都有兩個變換矩陣,您可以使用它們來操縱圖層及其內(nèi)容。 CALayertransform屬性指定要應(yīng)用于圖層及其嵌入的子圖層的轉(zhuǎn)換。 通常,當(dāng)您要修改圖層本身時,您可以使用此屬性。 例如,您可以使用該屬性縮放或旋轉(zhuǎn)圖層或暫時更改其位置。 sublayerTransform屬性定義了僅適用于子層的附加轉(zhuǎn)換,最常用于向場景內(nèi)容添加透視視覺效果。

通過將坐標(biāo)值乘以數(shù)字矩陣來轉(zhuǎn)換操作,以獲得代表原始點的轉(zhuǎn)換版本的新坐標(biāo)。 因為Core Animation值可以在三維中指定,所以每個坐標(biāo)點都有四個必須乘以4×4矩陣的值,如下圖所示。 在Core Animation中,圖中的變換由CATransform3D類型表示。 幸運的是,您不必直接修改此結(jié)構(gòu)的字段來執(zhí)行標(biāo)準(zhǔn)轉(zhuǎn)換。 核心動畫提供了一套全面的函數(shù)用于創(chuàng)建縮放,轉(zhuǎn)換和旋轉(zhuǎn)矩陣以及進行矩陣比較。 除了使用函數(shù)操縱變換之外,Core Animation還擴展了鍵值編碼KVC支持,以允許您使用關(guān)鍵路徑修改變換。 有關(guān)可以修改的關(guān)鍵路徑的列表,請參閱CATransform3D密鑰路徑 CATransform3D Key Paths。

下圖顯示了您可以進行的一些更常見的轉(zhuǎn)換的矩陣配置。 通過identity變換乘以任何坐標(biāo)返回完全相同的坐標(biāo)。 對于其他變換,如何修改坐標(biāo)完全取決于您更改的矩陣組件。 例如,要僅沿x軸轉(zhuǎn)換,您將為轉(zhuǎn)換矩陣的tx組件提供非零值,并將ty和tz值保留為0,對于旋轉(zhuǎn),您將提供目標(biāo)旋轉(zhuǎn)角度適當(dāng)?shù)恼液陀嘞抑怠?/p>

Matrix configurations for common transformations

有關(guān)用于創(chuàng)建和操作變換的功能的信息,請參閱Core Animation Function Reference。


Layer Trees Reflect Different Aspects of the Animation State - layer樹反映動畫狀態(tài)的不同方面

使用Core Animation的app有三組圖層layer對象,每套圖層對象在使您的app的內(nèi)容出現(xiàn)在屏幕上方面具有不同的作用:

  • 模型層樹(或簡稱“層樹”)中的對象是您的應(yīng)用程序與之最相互影響的對象。 此樹中的對象是存儲任何動畫的目標(biāo)值的模型對象。 無論何時更改圖層的屬性,都可以使用其中一個對象。

  • 展示樹中的對象包含任何正在運行的動畫的飛行中值。 而層樹對象包含動畫的目標(biāo)值,而呈現(xiàn)樹中的對象會反映當(dāng)前值在屏幕上顯示的值。 您不應(yīng)該修改此樹中的對象。 而是使用這些對象來讀取當(dāng)前的動畫值,也許是從這些值開始創(chuàng)建一個新的動畫。

  • 渲染樹中的對象執(zhí)行實際動畫,并且對Core Animation是私有的。

每組圖層layer對象被組織成層次結(jié)構(gòu),如app中的視圖。 實際上,對于一個能夠為其所有視圖啟用圖層的app,每個樹的初始結(jié)構(gòu)恰好匹配了視圖層次結(jié)構(gòu)。 但是,app可以根據(jù)需要向?qū)哟谓Y(jié)構(gòu)中添加額外的圖層layer對象(即與視圖無關(guān)的圖層)。 您可以在不需要視圖所有開銷的內(nèi)容的情況下優(yōu)化app的性能。 下圖顯示了在一個簡單的iOS app中找到的圖層layer細分。 示例中的窗口包含一個內(nèi)容視圖,該視圖本身包含一個按鈕視圖和兩個獨立的圖層對象。 每個視圖都有一個相應(yīng)的圖層對象,它形成圖層層次結(jié)構(gòu)的一部分。

對于圖層layer樹中的每個對象,展示樹和渲染樹中都有一個匹配的對象,如下圖所示。 如前所述,app主要使用圖層layer樹中的對象,但有時可以訪問展示樹中的對象。 具體來說,訪問layer樹中的對象的 presentationLayer屬性會返回呈現(xiàn)樹中的相應(yīng)對象。 您可能希望訪問該對象以讀取動畫中間的屬性的當(dāng)前值。

The layer trees for a window

重要:只有當(dāng)動畫在飛行中時,才能訪問展示樹中的對象。 當(dāng)動畫正在進行時,展示樹包含當(dāng)時在屏幕上顯示的圖層值。 此行為與圖層layer樹不同,圖層樹總是反映您代碼設(shè)置的最后一個值,相當(dāng)于動畫的最終狀態(tài)。


The Relationship Between Layers and Views - 圖層和視圖的關(guān)系

圖層不能替代您的app的視圖,也就是說,您無法僅基于圖層layer對象創(chuàng)建可視界面。 layer層為您的view提供基礎(chǔ)部分。 具體來說,圖層使繪圖和動畫視圖的內(nèi)容變得更加容易和有效,并且在執(zhí)行此操作時保持較高的幀速率。 但是,還是有很多事情層layer是不能做的。 層layer不能處理事件、繪制內(nèi)容、參與響應(yīng)者鏈或做許多其他事情。 因此,每個app仍然必須有一個或多個視圖來處理這些交互。

在iOS中,每個視圖都由相應(yīng)的圖層對象支持,但在OS X中,您必須確定哪些視圖應(yīng)具有圖層。 在OS X v10.8及更高版本中,將圖層添加到所有視圖可能是有意義的。 但是,您不需要這樣做,并且在開銷不合理和不必要的情況下仍可禁用層。 圖層確實會增加應(yīng)用程序的內(nèi)存開銷,但是它們的優(yōu)勢往往超過劣勢,因此在禁用層支持之前,最好測試應(yīng)用程序的性能。

為視圖啟用圖層支持時,可以創(chuàng)建所謂的支持層的視圖。 在層次支持的視圖中,系統(tǒng)負責(zé)創(chuàng)建底層圖層對象,并保持該圖層與視圖同步。 所有iOS視圖都是層次支持的,OS X中的大多數(shù)視圖也是如此。 但是,在OS X中,您還可以創(chuàng)建一個圖層托管視圖,這是您自己提供圖層對象的視圖。 對于層次托管視圖,AppKit采用手動管理層,不會修改它以響應(yīng)視圖更改。

注意:對于層次支持的視圖,建議您盡可能操縱視圖,而不是圖層。 在iOS中,視圖只是圍繞層對象的薄包裝,因此您對圖層進行的任何操作通常都可以正常工作。 但是在iOS和OS X中都有這樣的情況,其中操縱圖層而不是視圖可能不會產(chǎn)生所需的結(jié)果。 盡可能地,本文件指出了這些陷阱,并嘗試提供方法來幫助您解決這些問題。

除了與視圖相關(guān)聯(lián)的圖層之外,還可以創(chuàng)建沒有相應(yīng)視圖的圖層對象。 您可以將這些獨立圖層對象嵌入到應(yīng)用程序中的任何其他圖層對象中,包括與視圖關(guān)聯(lián)的圖層對象。 通常使用獨立圖層對象作為特定優(yōu)化路徑的一部分。 例如,如果要在多個地方使用相同的圖像,則可以加載圖像一次,并將其與多個獨立圖層對象相關(guān)聯(lián),并將這些對象添加到圖層樹中。 每個層然后引用源圖像,而不是嘗試在內(nèi)存中創(chuàng)建該圖像的自己的副本。

有關(guān)如何為應(yīng)用程序的視圖啟用圖層支持的信息,請參閱Enabling Core Animation Support in Your App。 有關(guān)如何創(chuàng)建層對象層次結(jié)構(gòu)的信息,以及有關(guān)何時可以這樣做的提示,請參閱Building a Layer Hierarchy。

后記

未完,待續(xù)~~~

最后編輯于
?著作權(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)容