概述
core Animation主要用于iOS和OS X 系統(tǒng)上做圖形渲染和動(dòng)畫(huà),你可以給app中的view或者可視元素做動(dòng)畫(huà)低千。繪制動(dòng)畫(huà)的每一幀的工作都是core animation 完成的配阵。我們需要做的至少配置一些動(dòng)畫(huà)參數(shù),比如起點(diǎn)終點(diǎn)示血,并且要告訴core Animation 啟動(dòng)就ok了棋傍。coreAnimation 會(huì)將剩下的工作提交給繪制硬件加速渲染,圖形加速渲染可以實(shí)現(xiàn)高幀速率和流暢的動(dòng)畫(huà)难审,而且也不會(huì)給cpu帶來(lái)負(fù)擔(dān)瘫拣。
coreAnimation 位于AppKit 和UIKit 之下,并且集成在了cocoa 和Cocoa Touch 的視圖工作流程中告喊。
coreAnimation 也暴露view的一些接口給我們麸拄,可以讓我們更好的控制動(dòng)畫(huà)派昧。
core Animation 管理屏幕顯示
這里需要明白,core Animation本身不是一個(gè)繪制系統(tǒng)感帅,他只是在硬件上用來(lái)合成或者操作app的內(nèi)容的基礎(chǔ)結(jié)構(gòu)斗锭。coreAnimation的核心是操作Calayer 對(duì)象,我們可以用Calyer對(duì)象來(lái)管理和操作顯示內(nèi)容失球。CAlayer可以將我們?cè)O(shè)置的內(nèi)容捕獲到可以到bitmap 位圖中岖是,方便圖形硬件處理。
圖層修改可以觸發(fā)動(dòng)畫(huà)
我們創(chuàng)建的大多數(shù)動(dòng)畫(huà)都涉及到到Calayer的屬性实苞,比如view豺撑,layer的bounds,positon黔牵,opacity聪轿,transform等,對(duì)于大多數(shù)這些屬性猾浦,更改屬性值會(huì)導(dǎo)致創(chuàng)建隱式動(dòng)畫(huà)陆错,layer會(huì)將屬性值從舊值設(shè)置成新值。如果我們想更多的控制生成的動(dòng)畫(huà)行為金赦,我們也可以顯式的設(shè)置這些屬性動(dòng)畫(huà)音瓷。
改變layer 的默認(rèn)行為
layer的隱式動(dòng)畫(huà)是用 action 對(duì)象的實(shí)現(xiàn)了。我們可以創(chuàng)建自己的action對(duì)象來(lái)實(shí)現(xiàn)自定義動(dòng)畫(huà)夹抗,也可以用action對(duì)象來(lái)實(shí)現(xiàn)其他類型的行為绳慎,然后,將操作對(duì)象分配給圖層的某個(gè)屬性漠烧。當(dāng)改屬性改變時(shí)杏愤,coreAnimation 將檢索您的操作對(duì)象并告訴action 執(zhí)行操作。
core Animation 基礎(chǔ)
core Animation 提供一個(gè)通用系統(tǒng)已脓,用于動(dòng)畫(huà)view 和別的可視元素珊楼。core Animation不能替代view,他是一種技術(shù)度液,能給view提供更好的性能和動(dòng)畫(huà)支持亥曹。 core Animation依靠緩存view的bitmaps圖來(lái)實(shí)現(xiàn)更好的性能和動(dòng)畫(huà)支持。
在某些情況下恨诱,我們可能需要考慮如何呈現(xiàn)和管理app coreAnimation緩存的這些內(nèi)容媳瞪,大多數(shù)情況下不需要考慮。
除了緩存view的bitmaps照宝,core Animation 還定義了一種指定任意可視內(nèi)容的方法蛇受,我們可以將該內(nèi)容與視圖集成,和其他內(nèi)容一起做動(dòng)畫(huà)厕鹃。
我們可以用Core Animation 為view和可視元素更改動(dòng)畫(huà)兢仰,大多數(shù)動(dòng)畫(huà)都與可視對(duì)象的屬性有關(guān)乍丈。例如,我們可以用core Animation 為視圖的position, size, or opacity.
layer繪制和動(dòng)畫(huà)基礎(chǔ)
layer是2d 和3d 和核心把将,與view 一樣轻专,layer 管理集合,內(nèi)容察蹲,可視屬性等请垛。與view不一樣的地方在于,layer不能定義自己的外觀洽议。layer只管理與bitmap 相關(guān)的狀態(tài)信息宗收,bitmap 自己僅是view繪制的一個(gè)結(jié)果,或者一樣不可改變的image而已亚兄。因此混稽,基于layer主要管理數(shù)據(jù),所以layers 可以理解為模型對(duì)象审胚。這個(gè)概念很重要匈勋,因?yàn)榭梢杂绊憚?dòng)畫(huà)的行為。
layer-模型對(duì)象
大多數(shù)layer不會(huì)進(jìn)行實(shí)際的繪制膳叨,而是捕獲app提供的內(nèi)容并將其緩存成bitmap圖洽洁,有時(shí)候也可以稱為backing store(備份?)懒鉴。當(dāng)改變layer屬性的時(shí)候,我們所做的只是更改了layer對(duì)象關(guān)聯(lián)的狀態(tài)信息碎浇。當(dāng)更改觸發(fā)動(dòng)畫(huà)時(shí)临谱,core Animation會(huì)將圖層的位圖和狀態(tài)信息傳遞給圖形硬件,圖形硬件會(huì)使用新信息渲染位圖奴璃。如圖所示悉默,在硬件中操作bitmap會(huì)產(chǎn)生比在軟件更快的動(dòng)畫(huà)
core Animation 操作的是靜態(tài)bitmap,所以基于layer的繪制與傳統(tǒng)的基于view繪制的技術(shù)有很大的不同苟穆。
用view繪制的時(shí)候抄课,對(duì)自身的更改會(huì)導(dǎo)致調(diào)用drawRect:方法,使用新參數(shù)重新繪制雳旅。但這種繪制是需要耗費(fèi)cpu的跟磨,因?yàn)檫@種操作是在主線程上使用CPU 完成的。而核心動(dòng)畫(huà)通過(guò)在硬件中操縱緩存的bitmap來(lái)實(shí)現(xiàn)相同或者類似的效果而避免消耗cpu的資源攒盈。
盡管core Animation 盡可能的使用緩存內(nèi)容抵拘,但是,我們?nèi)匀槐仨毺峁┏跏純?nèi)容并且時(shí)時(shí)更新才可以型豁。
layer-基礎(chǔ)動(dòng)畫(huà)
layer對(duì)象的數(shù)據(jù)和狀態(tài)信息與屏幕上改圖層可視化內(nèi)容是分離的僵蛛。這種分離提供了一種介入自身的方式尚蝌,以動(dòng)畫(huà)的方式讓其layer的舊值轉(zhuǎn)變成新值。例如:更改layer的位置屬性充尉,會(huì)導(dǎo)致CoreAnimation將圖層從當(dāng)前位置移動(dòng)到新指定的位置飘言。其他屬性也會(huì)產(chǎn)生適當(dāng)?shù)膭?dòng)畫(huà)。
在動(dòng)畫(huà)過(guò)程中驼侠,CoreAnimation 會(huì)在硬件中為您完成所有逐幀繪制姿鸿。我們只需要設(shè)置動(dòng)畫(huà)的起始點(diǎn)和終點(diǎn)就可以了,coreAnimation完成剩下的工作泪电。我們也可以根據(jù)需求指定自定義計(jì)時(shí)信息和動(dòng)畫(huà)參數(shù)般妙。否則使用CoreAnimation的默認(rèn)值
layer-定義自定義圖形
layer的一個(gè)功能之一是管理其內(nèi)容的可視形狀∠嗨伲可視形狀包含內(nèi)容的邊界碟渺,在屏幕的位置以及l(fā)ayer是否需要旋轉(zhuǎn),縮放突诬,變換信息苫拍。與view一樣,layer也有frame 和 bounds旺隙∪藜可以用position定位其位置。layer也有view不具有的屬性蔬捷,例如anchor point(用于定義操作發(fā)生的點(diǎn))垄提。指定layer的形狀有些方面還是和view不太一樣的
layer- 坐標(biāo)系
layer 使用兩種坐標(biāo)系,基于點(diǎn)的坐標(biāo)系和單位坐標(biāo)系來(lái)指定內(nèi)容的位置周拐。使用哪種坐標(biāo)系取決于所傳達(dá)的信息類型
- 點(diǎn)坐標(biāo)系:指定直接映射到屏幕坐標(biāo)的值或者是相對(duì)于另一個(gè)layer指定的值時(shí)铡俐。例如layer的poisition屬性
- 單位坐標(biāo)系:當(dāng)值不與屏幕坐標(biāo)相關(guān)聯(lián)時(shí)使用單位坐標(biāo)系。例如:anchorPoint
點(diǎn)坐標(biāo)系一般用于指定layer的大小和位置妥粟。bound屬性定義了圖層本身坐標(biāo)系和自身大小审丘。positon屬性定義圖層layer相對(duì)于父坐標(biāo)系的位置。雖然layer有frame屬性勾给,其實(shí)改屬性是positon和bound屬性派生出來(lái)的滩报。
layer 坐標(biāo)體系方向始終和底層平臺(tái)的默認(rèn)方向匹配。
在iOS中播急,默認(rèn)情況下脓钾,邊界矩形的原點(diǎn)位于圖層的左上角,而在OS X中桩警,它位于底部 - 左下角惭笑。
上圖有個(gè)positon屬性,定義在layer的中心,該屬性的值會(huì)因?yàn)閍nchorPoint屬性的改變而改變沉噩。
anchorPoint 屬于單位坐標(biāo)系捺宗,下面是單位坐標(biāo)系在個(gè)平臺(tái)的方向
ancorPoint 錨點(diǎn)使用
錨點(diǎn)與layer的幾何圖形有關(guān)系。錨點(diǎn)可以影響layer的positon 和 圖形變化(放大川蒙,縮小等)蚜厉。position 屬性始終相對(duì)于layer的錨點(diǎn)指定,并且layer的任何圖形變化transform都是基于錨點(diǎn)發(fā)生畜眨。
下圖演示如何將錨點(diǎn)從默認(rèn)值更改到不同值對(duì)layer positon的影響昼牛,即使layer沒(méi)有在super 的bounds內(nèi)移動(dòng),我們將錨點(diǎn)從layer的中心移動(dòng)到圖層的邊界康聂,原點(diǎn)也會(huì)更改poisition屬性中的值
我們將錨點(diǎn)從(0.5,0.5)移動(dòng)到(0贰健,0),假設(shè)layer的位置在屏幕上不變,那么layer的positon 也從(100恬汁,100)變成了(40伶椿,60)
下圖顯示錨點(diǎn)如何影響layer的transform。當(dāng)給layer旋轉(zhuǎn)變換時(shí)氓侧,旋轉(zhuǎn)會(huì)圍繞錨點(diǎn)旋轉(zhuǎn)脊另。默認(rèn)錨點(diǎn)位于中間。
如果我們不改默認(rèn)anchorPoint 值约巷,positon就相當(dāng)于UIView的center
如果anchorPoint 是(0偎痛,0)positon 就相當(dāng)于UIView的起始點(diǎn)
layer-三維變換
每個(gè)layer 有兩個(gè)變換矩陣,我們可以用他們來(lái)操作layer以及內(nèi)容独郎。layer的transform應(yīng)用于layer以及子layer的變換踩麦。通常,我們想要修改layer本身時(shí)候氓癌,可以用改屬性谓谦。我們可以用sublayerTransform屬性定義自圖層的轉(zhuǎn)換,最常用于向場(chǎng)景內(nèi)容透視效果
通常我們將坐標(biāo)值乘以數(shù)字矩陣來(lái)變換工作顽铸,以獲取變換后的新坐標(biāo)茁计。由于核心動(dòng)畫(huà)值可以在三維中指定料皇,因此每個(gè)坐標(biāo)值有四個(gè)值谓松,必須乘以一個(gè)四乘四的矩陣。在CoreNaimation中践剂,3D變換用CATransform3D 類型標(biāo)示鬼譬。我們不必修改次結(jié)構(gòu)的字段執(zhí)行標(biāo)準(zhǔn)轉(zhuǎn)換,core Animation提供了一整套功能逊脯,用于創(chuàng)建縮放优质,平移和旋轉(zhuǎn)矩陣以及進(jìn)行矩陣比較。除了使用函數(shù)操作變換之外,core Animation 還擴(kuò)展了鍵值編碼支持巩螃,運(yùn)行我們使用key Paths來(lái)修改變換演怎。
下圖顯示了我們可以進(jìn)行的一些常見(jiàn)的矩陣變化配置。
layer tree-動(dòng)畫(huà)狀態(tài)的不同方面
使用CoreAnimation 的應(yīng)用程序有三組layer對(duì)象避乏,每組layer對(duì)象在顯示屏幕內(nèi)容具有不同的作用
- 在layer Tree中的對(duì)象是我們與應(yīng)用程序交換的對(duì)象爷耀。在layerTree中的對(duì)象存儲(chǔ)動(dòng)畫(huà)的目標(biāo)值。當(dāng)改變layer的一個(gè)屬性拍皮,那意味著改變了layerTree中的一個(gè)layer
- presentation layerTree中的layer包含正在運(yùn)行的動(dòng)畫(huà)中的值歹叮。layerTree中的layer保存的是目標(biāo)值,而 presentation layerTree的layer保存的是當(dāng)前值铆帽,我們不應(yīng)該要改變presentation layerTree 中l(wèi)ayer的值咆耿。不過(guò),我們可以不可以修改爹橱,但可以讀取這些值萨螺。
- render tree 中執(zhí)行實(shí)際的動(dòng)畫(huà),這些動(dòng)畫(huà)是CoreAnimation私有的
每個(gè)layer對(duì)象都是以分層結(jié)構(gòu)組織起來(lái)的宅荤,就想view一樣屑迂。實(shí)際上,完全用view創(chuàng)建的應(yīng)用冯键,view的層次結(jié)構(gòu)和layer的層次結(jié)構(gòu)完全相同惹盼。
上圖顯示了一個(gè)app,改app的 window包含一個(gè)內(nèi)容view惫确,該view本身包含一個(gè)button和兩個(gè)獨(dú)立的layer對(duì)象手报。每個(gè)view都有一個(gè)對(duì)應(yīng)的layer對(duì)象,它構(gòu)成layer層次結(jié)構(gòu)的一部分改化。
對(duì)應(yīng)每個(gè)layerTree中的對(duì)象掩蛤,都有一個(gè)layer與presentation和render tree的對(duì)象相匹配。如圖所示陈肛,app主要使用的layer tree 中的對(duì)象揍鸟,但有時(shí)候可能會(huì)訪問(wèn)presentation tree中對(duì)象。具體來(lái)講句旱,訪問(wèn) 在layer tree中的presentation 層的對(duì)象阳藻,會(huì)返回presentation層中的對(duì)象。比如想訪問(wèn)動(dòng)畫(huà)執(zhí)行到中間的當(dāng)前值谈撒。
重要提示
我們?cè)L問(wèn) presentation tree 的對(duì)象僅應(yīng)該在動(dòng)畫(huà)播放的時(shí)候訪問(wèn)腥泥。當(dāng)動(dòng)畫(huà)正在進(jìn)行的時(shí)候, presentation tree 包含當(dāng)時(shí)在屏幕顯示的layer屬性當(dāng)前值啃匿。此行為與layer tree不一樣蛔外,layer tree始終顯示的代碼設(shè)置的最后值蛆楞,等效于動(dòng)畫(huà)的最終狀態(tài)
layer和view 的關(guān)系
layer不是view 的替代品,也就是說(shuō)夹厌,我們沒(méi)有辦法基于layer 創(chuàng)建可視化界面豹爹。layer只是為view提供基礎(chǔ)結(jié)構(gòu)。具體而言矛纹,layer可以更輕松帅戒,更高效的繪制和動(dòng)畫(huà)視圖內(nèi)容,并且可以保持高幀速度崖技。但是逻住,layer好多事情沒(méi)有做。layer 不處理時(shí)間迎献,繪制內(nèi)容瞎访,參與響應(yīng)鏈或者執(zhí)行許多其他操作。處于這些原因吁恍,每個(gè)app必須有一個(gè)或者多個(gè)view來(lái)處理這些類型的交互扒秸。
在ios中,每個(gè)view都有相應(yīng)的layer相對(duì)應(yīng)冀瓦。所有ios視圖都是圖層支持的伴奥。
對(duì)于支持layer的view,apple建議我們盡量操作view而不是操作layer翼闽。在ios中拾徙,view只是layer對(duì)象的簡(jiǎn)單封裝,一般情況下只要是view能滿足條件就是用view吧感局。除非view不能滿足要求尼啡,那么就只能是用layer了。
除了與view相關(guān)聯(lián)的layer询微,我們還可以自己創(chuàng)建沒(méi)有view的layer崖瞭,這些layer可以添加到app的任何layer中,包括與view相關(guān)聯(lián)的layer撑毛。通常书聚,我們使用單獨(dú)的layer對(duì)象作為特定優(yōu)化路徑的一部分。例如:如果我們要在多個(gè)位置使用相同的圖像藻雌,我們可以加載圖像一次雌续,并將其與懂個(gè)獨(dú)立層對(duì)象關(guān)聯(lián),并將這些對(duì)象添加到layer tree中蹦疑。然后西雀,每個(gè)層引用源對(duì)象萨驶,而不是嘗試在內(nèi)存中創(chuàng)建自己的圖像副本歉摧。