本文首發地址html
翻譯說明
Layer - 圖層
View - 視圖
複製代碼
Core Animation 提供一個通用的系統來對你 App 的視圖或者其餘可視化元素作動畫。Core Animation 並非替換你 App 的視圖,Core Animation 是一種與視圖集成的技術,用來給視圖內容的動畫製做提供更好的性能和支持。Core Animation 經過緩存視圖內容轉換爲圖形硬件能直接操做的位圖來實現這一行爲。在某些狀況下,爲了緩存視圖內容,Core Animation 還定義了一種方法來指定任意可見內容,將該內容與你的視圖集成,並將其與其餘全部內容一塊兒進行動畫。git
你使用 Core Animation 來對你 App 的視圖和可視對象的改變進行動畫。大多數的改變是和你修改的可視化對象的屬性相關聯的。例如:你可能使用 Core Animation 去使視圖的 position size 或 opacity 的改變進行動畫。當你進行相似的改變時,Core Animation 會在該屬性的當前值和你指定的新值之間作動畫。一般,你不會像動畫片同樣,使用 Core Animation 每秒60次來替換視圖的內容。實際上,你會使用 Core Animation 去移動屏幕上視圖的內容,淡入淡出內容,對視圖應用任意圖形形變,或者改變視圖的其餘可視屬性。github
圖層對象是由 3D 空間管理的 2D surface,它也是 Core Animation的靈魂。和視圖相同的是,圖層管理 surface 的幾何信息,內容,和它可視化屬性。和視圖不一樣的是,圖層不定義它們本身的外觀。圖層 對象僅管理位圖的狀態信息。位圖能夠是視圖繪製自身的結果,也能夠是你指定的 image。爲此,你在 App 中使用的 main layers 被認爲是模型對象,由於它們主要是管理數據。
這個概念很重要,由於它影響動畫的行爲。緩存
你的 App 中大多數的圖層不會作實際的繪製工做,圖層對象會捕獲你的 App 中提供的內容,而後將內容緩存爲位圖,有時也被稱爲 backing store。當你後面再修改圖層的屬性時,你所作的只是改變與圖層對象相關聯的狀態信息。當改變觸發一個動畫時,Core Animation 會將圖層的位圖和狀態信息傳遞給圖形硬件,圖形硬件使用新的信息來進行渲染,如圖1-1。硬件操做位圖進行動畫要比軟件快得多。 bash
由於它操做的是靜態的位圖,因此基於圖層的繪製與傳統的基於視圖的繪製技術有很大的不一樣。基於視圖的繪製,經過調用視圖的 drawRect:
方法去使用新的參數去重繪內容來做爲視圖自己改變的結果。可是使用這種方法是很是耗性能的,由於他在主線程上使用 CPU 。Core Animation 經過硬件直接操做緩存的位圖去實現一樣的或者相似的效果,來避免性能上的消耗。app
雖然 Core Animation 儘量的使用緩存的內容,可是你的 APP 必須提供初始的內容而且不時的更新它。你的 App 有幾種方法來提供圖層對象的內容,詳情請見提供圖層內容。ide
圖層對象的數據和狀態信息是與屏幕上圖層的視覺顯示分離的。這種分離賦予 Core Animation 一種方式去幹預本身,而且對舊狀態到新狀態的改變進行動畫。例如,改變圖層的 position
屬性 會致使 Core Animation 將圖層從當前位置移動到新的指定位置。一樣的,改變其餘的屬性也會致使恰當的改變。如圖1-2。圖層 屬性觸發動畫機制的列表,可參見可動畫的屬性。函數
在一個動畫執行的過程當中,Core Animation 會在硬件中完成全部的逐幀繪製。你所須要作的就是:給動畫制定一個開始值和一個結束值,剩下的就能夠交給 Core Animation 了。你也能夠自定義你所須要的時間信息和動畫參數,若是你不自定義,Core Animation 會提供合適的默認值。post
關於如何初始化動畫和配置動畫參數的更多信息,能夠參見動畫圖層內容。性能
圖層的工做之一就是管理其內容的視覺幾何(visual geometry)。視覺幾何包含其內容的 bounds、在屏幕的 position 和圖層是否被旋轉、縮放、形變。和視圖同樣,圖層也有 frame、bounds 屬性用來定位圖層的位置和內容。圖層還有視圖沒有的屬性,例如 錨點(anchor point):它定義了操做發生的點。 指定圖層幾何圖形的某些方面的方式也與爲視圖指定信息的方式不一樣。
圖層利用基於點座標系(point-based coordinate systems)和單位座標系(unit coordinate systems)來指定內容的位置。使用哪個座標系取決於傳遞信息的類型。當指定的值直接映射到屏幕座標或必須指定相關聯的另外一個圖層的值時,使用基於點座標系。例如圖層的 position
屬性。當值不該與屏幕座標相關聯,由於它與其餘值相關聯時,使用單位座標系。例如:圖層的 anchorPoint
屬性指一個與圖層自己的 bounds
相關聯的點,該點是能夠改變的。
基於點座標系最多見的用法就是使用圖層的 bounds
和 position
屬性指定圖層的 size
和 position
。bounds
定義了它自身的座標系,幷包含了它在屏幕上的 size
。position 定義了圖層在它父座標系上的位置。雖然圖層有 frame 的屬性,但該值實際是由 bounds
和 position
屬性計算出來的,而且圖層不會常用 frame。
layer 的 bounds
和 frame
屬性的方向老是和底層平臺的方向一致。下圖展現了 iOS 和 OS X 系統的默認方向。在 iOS 中,默認的原點是圖層的左上角,而在 OS X 系統上,默認是左下角。若是你想在兩個系統上用一套 Core Animation 代碼,你必須考慮到這些差別。
在圖1-3中,須要注意的是, position 屬性是位於圖層的中間。position 是基於圖層的 anchorPoint 屬性的值改變的幾個屬性之一。錨點表示座標的起始點,更多詳細信息請看 錨點影響幾何操做 章節。
錨點是使用單位座標系指定的幾個屬性之一。 Core Animation 使用單位座標系表示當圖層的尺寸發生改變時,值可能改變的屬性。你能夠將單位座標系視爲指定總可能值得百分比。單位座標中每一個單位座標的值的範圍都是 0.0 到 1.0 。例如,在 x 軸,左邊緣的座標是 0.0 ,右邊緣的座標是 1.0 。在 y 軸,單位座標值的方向改變取決於所在平臺,如圖1-4所示:
OS X 10.8 以前,當你須要的時候,可使用 geometryFlipped
屬性去改變圖層y 軸上的默認方向。當涉及到 filp 形變的時候,必須使用該屬性去幫助圖層獲得正確的方向。例如:若是父視圖使用 flip 形變,它的子視圖的內容(以及與它們綁定的 layers)每每會倒置。在這種狀況下,將子圖層的 geometryFilpped
屬性設置爲 YES ,是一種簡單有效的解決辦法。在 OS X 10.8 之後,AppKit 將會自動處理該屬性,不須要你再修改。對於 iOS 來講,推薦你不要使用 geometryFlipped
屬性。
全部的座標值,不管是點仍是單位座標值都是浮點數。使用浮點數能夠容許你在正常的座標值之間指定精確的位置。使用浮點數是很便捷的,尤爲在輸出或者繪製 Retina 顯示器時,一個點是由多個像素點繪製的。浮點數使你能夠忽略底層設備分辨率而專一於你所需精度的具體值。
layer 的幾何操做的發生於圖層的錨點相關聯,你可使用 anchorPoint
屬性來訪問圖層的錨點。當操做圖層的 position
或 transform
屬性時,錨點的影響是很是顯著地。position
屬性老是和圖層的錨點相關聯的,你應用到圖層上的任何形變效果也是和錨點相關聯的。
圖1-5 演示了錨點從默認值改變爲一個不一樣的值時,圖層的 position
屬性是如何變化的。即便圖層沒有在它的父邊界中沒有移動,將圖層的錨點從中心移動到邊界的原點也會改變 position
的值。
圖1-6 展現了改變錨點的值是如何影響形變在圖層上的應用。當你在圖層上應用一個旋轉的形變,旋轉發生在錨點的周圍。由於錨點默認是在圖層的中間,這一般會建立一個你期待的旋轉行爲,若是你改變錨點,旋轉的結果是不一樣的。
每一個圖層有兩個形變矩陣,你能夠用這兩個矩陣去操做圖層和它的內容。CALayer 的 transform
指的是你想應用在它和它的 sublayers 上形變。在你想改變圖層自己的時候使用該屬性。例如,你可能想使用該屬性去縮放、旋轉或者暫時改變它的 position。sublayerTransform
屬性只應用於 sublayers,它一般用於向場景內容添加透視效果。
經過將座標值乘以數字矩陣來進行形變工做,以得到表示原始點形變版本的新座標。由於 Core Animation 的值能夠在三維空間中指定,每一個座標點有四個值,座標點必須和一個 4x4 矩陣相乘,如圖1-7所示。在 Core Animation,圖中的形變是經過 CATransformD 類型來表示的。幸運的是,你沒必要去修改矩陣結構的字段來執行標準的形變。Core Animation 提供了豐富的函數去建立縮放、平移和旋轉矩陣去作矩陣比較。爲了使用函數來操做形變,Core Animation 延伸了鍵值編碼支持,使你可使用鍵來修改形變。查看 CATransform3D 鍵路徑 獲悉你可修改的鍵。
圖1-8 顯示了一些常見形變的矩陣配置。任何座標乘以 identity 矩陣返回座標自己。對於其餘形變,座標的修改徹底取決於你改變的矩陣元素。例如,沿 x軸平移,你能夠將形變矩陣的 tx 設爲非零值,將 ty 和 tz 設爲0。對於旋轉,你能夠提供目標旋轉角度響應的正弦值和餘弦值。
App 使用 Core Animation 有三組圖層對象。每組的圖層對象對將你的 App 的內容顯示在屏幕上都有不一樣的做用:
每組圖層對象都被組織成一個分層結構,就像 App 中的視圖。實際上, 對於爲其全部視圖啓用圖層的 App,每一個樹的初始結構徹底匹配視圖層次結構。可是,App 能夠根據須要將其餘圖層對象(即與視圖無關的圖層)添加到圖層層次結構中。你能夠在這種狀況下執行此操做,以針對不須要視圖的全部開銷的內容優化應用程序的性能。圖1-9顯示了在簡單的iOS應用程序中找到的圖層細分。示例中的 window 包含一個內容視圖,該視圖自己包含一個按鈕視圖和兩個獨立的圖層對象。每一個視圖都有一個對應的圖層對象,它構成圖層層次結構的一部分。
圖層樹中的每一個對象,都在表示樹和渲染樹中有一個與之匹配的對象,如圖1-10 所示。如上所述, App 主要使用圖層樹中的對象,但有時也會訪問表示樹中的對象。具體而言,訪問圖層樹中的對象的 presentationLayer
屬性來獲取表示樹中與之關聯的對象。你可能須要訪問對象來獲取動畫中間過程的屬性的值。
你應該只在動畫執行中的時候去訪問表示樹中的對象。當動畫正在進行時,表示樹包含當時在屏幕上顯示的圖層值。這個行爲不一樣於圖層樹,圖層樹老是反映你的代碼設置的最後的值,而且等同於動畫的最終狀態。
圖層不能替代你 App 中的視圖,即你不能僅基於圖層來建立視覺頁面。圖層提供視圖的基礎結構。圖層使繪製和動畫視圖的內容更加容易高效,而且保持高幀速率。然而,圖層也有不少事情處理不了。圖層不能處理事件、繪製內容、參與響應鏈,和其它不少事情。基於此,每一個 App 必須有一個或者多個視圖來處理上述類型的交互。
在 iOS 中,每一個視圖底層都由圖層對象支持,可是在 OS X 你必須決定哪一個視圖有圖層。在 OS X v10.8 之後的版本,給全部的視圖添加圖層多是有意義的。然而,你不被要求必須這麼作,你能夠在不須要或者不想的地方使圖層失效。圖層會使你的內存開銷增長,可是它們的優勢遠遠超過這個缺點。在禁用圖層支持以前,最好先測試 App 的性能。
當你的視圖支持圖層的時候,你建立了一個圖層支持的視圖(layer-backed view)。對於圖層支持的視圖,系統會在底層建立一個圖層對象,而且保持圖層和視圖同步。 iOS 的全部視圖和大部分的 OS X 視圖是圖層支持的視圖。然而,在 OS X 中,你也能夠建立圖層託管視圖(layer-hosting view),即你本身建立圖層對象的視圖。對於圖層託管視圖,AppKit採用了一種不干涉的方法來管理該層,而且不會根據視圖的變化來修改它。
對於圖層支持視圖,不管什麼時候,推薦你操做視圖,而不是圖層。在 iOS ,視圖只是圖層的一種封裝,因此,你在圖層上作的任何操做一般會正常工做。可是在 iOS 和 OS X 中都存在這樣的狀況:操縱圖層而不是視圖可能沒法產生預期的結果。只要有可能,本文檔指出了這些陷阱,並試圖提供方法來幫助你解決這些問題。
除了與視圖關聯的圖層以外,還能夠建立沒有相應視圖的圖層對象。你能夠將這些獨立的圖層對象嵌入到 App 中的任何其餘圖層對象中,包括那些與視圖相關聯的圖層對象。你一般使用獨立的圖層對象做爲特定優化路徑的一部分。例如,若是你想在多個地方使用相同的圖像,你能夠加載圖像一次,並將其與多個獨立的圖層對象相關聯,而後將這些對象添加到圖層樹中。而後,每一個圖層引用源圖像,而不是試圖在內存中建立本身的圖像副本。
有關如何爲應用程序視圖啓用圖層支持的信息,請參見在你的 App 中支持 Core Animation。有關如何建立圖層對象層次結構的信息,以及什麼時候建立圖層對象層次結構的提示,請參見構建圖層層次結構。