CoreAnimation初探(二) —— 初識(shí)CALayer與動(dòng)畫(huà)

上篇提到CoreAnimation是在圖形層之上捌刮,我們先看下CoreAnimation在框架中的位置:


CoreAnimation屬于QuartzCore框架平窘,Quartz原本是macOS的Darwin核心之上的繪圖技術(shù)。在iOS中,我們所看到的視圖UIView是通過(guò)QuartzCore中的CALayer顯示出來(lái)的兰珍,我們討論的動(dòng)畫(huà)效果也是加在這個(gè)CALayer上的锉矢。

圖層類是CoreAnimation的基礎(chǔ)梯嗽,它提供了一套抽象概念。CALayer是整個(gè)圖層類的基礎(chǔ)沽损,它是所有核心動(dòng)畫(huà)圖層類的父類慷荔。

本篇主要談?wù)凜ALayer(圖層類)和CAAnimation(動(dòng)畫(huà)類)的內(nèi)容和類關(guān)系,以及它們實(shí)現(xiàn)的一個(gè)重要的協(xié)議CAMediaTiming缠俺。


1.CALayer

為什么UIView要加一層Layer來(lái)負(fù)責(zé)顯示呢显晶?我們知道QuartzCore是跨iOS和macOS平臺(tái)的,而UIView屬于UIKit是iOS開(kāi)發(fā)使用的壹士,在macOS中對(duì)應(yīng)AppKit里的NSView磷雇。這是因?yàn)閙acOS是基于鼠標(biāo)指針操作的系統(tǒng),與iOS的多點(diǎn)觸控有本質(zhì)的區(qū)別躏救。雖然iOS在交互上與macOS有所不同唯笙,但在顯示層面卻可以使用同一套技術(shù)螟蒸。

// UIView中與layer相關(guān)的屬性方法
@interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>

/* layer的class,默認(rèn)為CALayer崩掘,可以用自定義的layer */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) Class layerClass;                        // default is [CALayer class]. Used when creating the underlying layer for the view.
#else
+ (Class)layerClass;                        // default is [CALayer class]. Used when creating the underlying layer for the view.
#endif

/* view的leyer七嫌,view是layer的代理 */
@property(nonatomic,readonly,strong)                 CALayer  *layer;              // returns view's layer. Will always return a non-nil value. view is layer's delegate

可以想象下我們看到的view實(shí)際上都是它的layer,我們先通過(guò)CALayer中幾何相關(guān)的屬性來(lái)認(rèn)識(shí)下它:

  • bounds:圖層的bounds是一個(gè)CGRect的值苞慢,指定圖層的大小(bounds.size)和原點(diǎn)(bounds.origin)
/* The bounds of the layer. Defaults to CGRectZero. Animatable. */
@property CGRect bounds;
  • position:指定圖層的位置(相對(duì)于父圖層而言)
/* The position in the superlayer that the anchor point of the layer's
 * bounds rect is aligned to. Defaults to the zero point. Animatable. */
@property CGPoint position;
  • anchorPoint:錨點(diǎn)指定了position在當(dāng)前圖層中的位置诵原,坐標(biāo)范圍0~1。position點(diǎn)的值是相對(duì)于父圖層的挽放,而這個(gè)position到底位于當(dāng)前圖層的什么地方绍赛,是由錨點(diǎn)決定的。(默認(rèn)在圖層的中心辑畦,即錨點(diǎn)為(0.5,0.5) )
/* Defines the anchor point of the layer's bounds rect, as a point in
 * normalized layer coordinates - '(0, 0)' is the bottom left corner of
 * the bounds rect, '(1, 1)' is the top right corner. Defaults to
 * '(0.5, 0.5)', i.e. the center of the bounds rect. Animatable. */
@property CGPoint anchorPoint;
  • transform:指定圖層的幾何變換吗蚌,類型為上篇說(shuō)過(guò)的CATransform3D
/* A transform applied to the layer relative to the anchor point of its
 * bounds rect. Defaults to the identity transform. Animatable. */
@property CATransform3D transform;

這些屬性的注釋最后都有一句Animatable,就是說(shuō)我們可以通過(guò)改變這些屬性來(lái)實(shí)現(xiàn)動(dòng)畫(huà)纯出。默認(rèn)地蚯妇,我們修改這些屬性都會(huì)導(dǎo)致圖層從舊值動(dòng)畫(huà)顯示為新值,稱為隱式動(dòng)畫(huà)暂筝。(注意箩言,修改UIView自帶的layer(root layer)是沒(méi)有隱式動(dòng)畫(huà)的)

還有一個(gè)屬性比較特殊,那就是layer的frame:

/* Unlike NSView, each Layer in the hierarchy has an implicit frame
 * rectangle, a function of the `position', `bounds', `anchorPoint',
 * and `transform' properties. When setting the frame the `position'
 * and `bounds.size' are changed to match the given frame. */
@property CGRect frame;

注意到frame的注釋里面是沒(méi)有Animatable的乖杠。事實(shí)上分扎,我們可以理解為圖層的frame并不是一個(gè)真實(shí)的屬性:當(dāng)我們讀取frame時(shí),會(huì)根據(jù)圖層position胧洒、bounds畏吓、anchorPoint和transform的值計(jì)算出它的frame;而當(dāng)我們?cè)O(shè)置frame時(shí)卫漫,圖層會(huì)根據(jù)anchorPoint改變position和bounds菲饼。也就是說(shuō)frame本身并沒(méi)有被保存。

圖層不但給自己提供可視化的內(nèi)容和管理動(dòng)畫(huà)列赎,而且充當(dāng)了其他圖層的容器類宏悦,構(gòu)建圖層層次結(jié)構(gòu)

圖層樹(shù)類似于UIView的層次結(jié)構(gòu),一個(gè)view實(shí)例擁有父視圖(superView)和子視圖(subView)包吝;同樣一個(gè)layer也有父圖層(superLayer)和子圖層(subLayer)饼煞。我們可以直接在view的layer上添加子layer達(dá)到一些顯示效果,但這些單獨(dú)的layer無(wú)法像UIView那樣進(jìn)行交互響應(yīng)诗越。

2.CAAnimation

CALayer提供以下方法來(lái)管理動(dòng)畫(huà):


- (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)key;

- (void)removeAllAnimations;

- (void)removeAnimationForKey:(NSString *)key;

- (nullable NSArray<NSString *> *)animationKeys;

- (nullable CAAnimation *)animationForKey:(NSString *)key;

CAAnimation是動(dòng)畫(huà)基類砖瞧,我們常用的CABasicAnimation和CAKeyframeAnimation都繼承于CAPropertyAnimation即屬性動(dòng)畫(huà)。屬性動(dòng)畫(huà)通過(guò)改變layer的可動(dòng)畫(huà)屬性(位置嚷狞、大小等)實(shí)現(xiàn)動(dòng)畫(huà)效果块促。CABasicAnimation可以看做有兩個(gè)關(guān)鍵幀的CAKeyframeAnimation荣堰,通過(guò)插值形成一條通過(guò)各關(guān)鍵幀的動(dòng)畫(huà)路徑。但CABasicAnimation更加靈活一些:

@interface CABasicAnimation : CAPropertyAnimation
/* 我們可以通過(guò)下面三個(gè)值來(lái)規(guī)定CABasicAnimation的動(dòng)畫(huà)起止?fàn)顟B(tài)
 * 這三個(gè)屬性都是可選的竭翠,通常給定其中一個(gè)或者兩個(gè)振坚,以下是官方建議的使用方式
 * * 給定fromValue和toValue,將在兩者之間進(jìn)行插值 *
 * * 給定fromValue和byValue斋扰,將在fromValue和fromValue+byValue之間插值 *
 * * 給定byValue和toValue渡八,將在toValue-byValue和toValue之間插值 *
 * * 僅給定fromValue,將在fromValue和當(dāng)前值之間插值 *
 * * 僅給定toValue褥实,將在當(dāng)前值和toValue之間插值 *
 * * 僅給定byValue呀狼,將在當(dāng)前值和當(dāng)前值+byValue之間插值 * */
@property(nullable, strong) id fromValue;
@property(nullable, strong) id toValue;
@property(nullable, strong) id byValue;

@end

在CAKeyframeAnimation中裂允,除了給定各關(guān)鍵幀之外還可以指定關(guān)鍵幀之間的時(shí)間和時(shí)間函數(shù):

@interface CAKeyframeAnimation : CAPropertyAnimation

@property(nullable, copy) NSArray *values;
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;
/* 時(shí)間函數(shù)有線性损离、淡入、淡出等簡(jiǎn)單效果绝编,還可以指定一條三次貝塞爾曲線 */
@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;

@end

到這我們已經(jīng)能夠感覺(jué)到僻澎,所謂動(dòng)畫(huà)實(shí)際上就是在不同的時(shí)間顯示不同畫(huà)面,時(shí)間在走進(jìn)而形成連續(xù)變化的效果十饥。所以窟勃,動(dòng)畫(huà)的關(guān)鍵就是對(duì)時(shí)間的控制。

3.CAMediaTiming

CAMediaTiming是CoreAnimation中一個(gè)非常重要的協(xié)議渡紫,CALayer和CAAnimation都實(shí)現(xiàn)了它來(lái)對(duì)時(shí)間進(jìn)行管理足删。協(xié)議定義了8個(gè)屬性僻焚,通過(guò)它們來(lái)控制時(shí)間,這些屬性大都見(jiàn)名知意:

@protocol CAMediaTiming

@property CFTimeInterval beginTime;
@property CFTimeInterval duration;
@property float speed;
/* timeOffset時(shí)間的偏移量汁咏,用它可以實(shí)現(xiàn)動(dòng)畫(huà)的暫停、繼續(xù)等效果 */
@property CFTimeInterval timeOffset;
@property float repeatCount;
@property CFTimeInterval repeatDuration;
/* autoreverses為true時(shí)時(shí)間結(jié)束后會(huì)原路返回作媚,默認(rèn)為false */
@property BOOL autoreverses;
/* fillMode填充模式攘滩,有4種,見(jiàn)下 */
@property(copy) NSString *fillMode;

@end

NSString * const kCAFillModeForwards;  // 向前填充纸泡,結(jié)束后保持狀態(tài)
NSString * const kCAFillModeBackwards;  // 向后填充漂问,開(kāi)始之前維持開(kāi)始狀態(tài)
NSString * const kCAFillModeBoth;  // 前后填充,同時(shí)保持前后狀態(tài)
NSString * const kCAFillModeRemoved;  // 無(wú)填充女揭,結(jié)束后移除蚤假,fillMode默認(rèn)為這個(gè)值

下面這張圖形象的說(shuō)明了這些屬性是如何靈活的進(jìn)行動(dòng)畫(huà)時(shí)間控制的:

動(dòng)畫(huà)時(shí)間控制

這張圖的出處,以及有關(guān)CAMediaTiming的時(shí)間控制吧兔,可以參考Controlling Animation TimingiOS CoreAnimation專題——原理篇(四)動(dòng)畫(huà)時(shí)間控制磷仰,里面介紹的非常詳細(xì)。需要注意的是掩驱,CALayer也實(shí)現(xiàn)了CAMediaTiming協(xié)議芒划,也就是說(shuō)如果我們將layer的speed設(shè)置為2冬竟,那么加到這個(gè)layer上的動(dòng)畫(huà)都會(huì)以兩倍速執(zhí)行。


本篇從圖層民逼、動(dòng)畫(huà)和時(shí)間控制的關(guān)系上簡(jiǎn)單認(rèn)識(shí)了CALayer泵殴、屬性動(dòng)畫(huà)和動(dòng)畫(huà)時(shí)間控制,了解屬性動(dòng)畫(huà)是根據(jù)時(shí)間在各關(guān)鍵幀之間進(jìn)行插值拼苍,隨時(shí)間連續(xù)改變layer的某動(dòng)畫(huà)屬性來(lái)實(shí)現(xiàn)的笑诅。

參考資料

對(duì)CoreGraphics和QuartzCore的理解
Quartz 2D 繪圖技術(shù)
Core Animation基礎(chǔ)介紹、簡(jiǎn)單使用CALayer以及多種動(dòng)畫(huà)效果
通過(guò)CALayer讓你的APP動(dòng)起來(lái)
Controlling Animation Timing
iOS CoreAnimation專題——原理篇(四)動(dòng)畫(huà)時(shí)間控制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疮鲫,一起剝皮案震驚了整個(gè)濱河市吆你,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俊犯,老刑警劉巖妇多,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異燕侠,居然都是意外死亡者祖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)绢彤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)七问,“玉大人,你說(shuō)我怎么就攤上這事茫舶⌒笛玻” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵饶氏,是天一觀的道長(zhǎng)讥耗。 經(jīng)常有香客問(wèn)我,道長(zhǎng)嚷往,這世上最難降的妖魔是什么葛账? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮皮仁,結(jié)果婚禮上籍琳,老公的妹妹穿的比我還像新娘。我一直安慰自己贷祈,他們只是感情好趋急,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著势誊,像睡著了一般呜达。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粟耻,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天查近,我揣著相機(jī)與錄音眉踱,去河邊找鬼。 笑死霜威,一個(gè)胖子當(dāng)著我的面吹牛谈喳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播戈泼,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼婿禽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了大猛?” 一聲冷哼從身側(cè)響起扭倾,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挽绩,沒(méi)想到半個(gè)月后膛壹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡琼牧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年恢筝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哀卫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巨坊。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖此改,靈堂內(nèi)的尸體忽然破棺而出趾撵,到底是詐尸還是另有隱情,我是刑警寧澤共啃,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布占调,位于F島的核電站,受9級(jí)特大地震影響移剪,放射性物質(zhì)發(fā)生泄漏究珊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一纵苛、第九天 我趴在偏房一處隱蔽的房頂上張望剿涮。 院中可真熱鬧,春花似錦攻人、人聲如沸取试。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瞬浓。三九已至,卻和暖如春蓬坡,著一層夾襖步出監(jiān)牢的瞬間猿棉,已是汗流浹背磅叛。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萨赁,地道東北人宪躯。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像位迂,于是被迫代替她去往敵國(guó)和親访雪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果掂林,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜臣缀,今天將帶大家一窺ios動(dòng)畫(huà)全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,471評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果泻帮,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜精置,今天將帶大家一窺iOS動(dòng)畫(huà)全貌。在這里你可以看...
    F麥子閱讀 5,104評(píng)論 5 13
  • Core Animation其實(shí)是一個(gè)令人誤解的命名锣杂。你可能認(rèn)為它只是用來(lái)做動(dòng)畫(huà)的脂倦,但實(shí)際上它是從一個(gè)叫做Laye...
    小貓仔閱讀 3,691評(píng)論 1 4
  • 書(shū)寫(xiě)的很好,翻譯的也棒元莫!感謝譯者赖阻,感謝感謝! iOS-Core-Animation-Advanced-Techni...
    錢(qián)噓噓閱讀 2,293評(píng)論 0 6
  • 曾經(jīng)信誓旦旦揚(yáng)言 曾經(jīng)看厭煩惱無(wú)數(shù) 曾經(jīng)不屑還被情困 如今也非昔日光景 如今也是難以啟齒 如今也是曾經(jīng)厭惡 倒不如...
    阿火moete閱讀 249評(píng)論 0 0