iOS Core Animation詳解

一、CoreGraphics,QuartzCore, CoreAnimation區(qū)別

CoreGraphics(核心圖形)

它是iOS的核心圖形庫(kù),包含Quartz2D繪圖API接口,常用的是point,size,rect等這些圖形,都定義在這個(gè)框架中,類名以CG開(kāi)頭的都屬于CoreGraphics框架,它提供的都是C語(yǔ)言函數(shù)接口,是可以在iOS和mac OS 通用的

QuartzCore

Quartz是位于Mac OS X的Drawin核心之上的繪圖層

Core Animation

Core Animation,中文翻譯為核心動(dòng)畫,它是一組非常強(qiáng)大的動(dòng)畫處理API,使用它能做出非??犰诺膭?dòng)畫效果。CoreAnimation是跨平臺(tái)的,既可以支持IOS,也支持MAC OS。Core Animation的動(dòng)畫執(zhí)行過(guò)程都是在后臺(tái)操作的,不會(huì)阻塞主線程。要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。

image.png

二、Core Animation的繼承結(jié)構(gòu)

CAAnimation是所有動(dòng)畫對(duì)象的父類,負(fù)責(zé)控制動(dòng)畫的持續(xù)時(shí)間和速度、是個(gè)抽象類,不能直接使用,應(yīng)該使用具體子類。需要注意的是CAAnimation 和 CAPropertyAnimation 都是抽象類。

view是負(fù)責(zé)響應(yīng)事件的,layer是負(fù)責(zé)顯示的。


image.png

黃色的區(qū)塊是常用的屬性、方法或者需要遵守的協(xié)議,灰色是類名。
核心動(dòng)畫中所有類都遵守CAMediaTiming。

  • CAAnaimation是個(gè)抽象類,不具備動(dòng)畫效果,必須用它的子類CAAnimationGroup和CATransition)才有動(dòng)畫效果。
  • CAAnimationGroup(動(dòng)畫組),可以同時(shí)進(jìn)行縮放,旋轉(zhuǎn)。
  • CATransition(轉(zhuǎn)場(chǎng)動(dòng)畫),界面之間跳轉(zhuǎn)都可以用轉(zhuǎn)場(chǎng)動(dòng)畫。
  • CAPropertyAnimation也是個(gè)抽象類,本身不具備動(dòng)畫效果,只有子類(CABasicAnimation和CAKeyframeAnimation)才有動(dòng)畫效果。
  • CABasicAnimation(基礎(chǔ)動(dòng)畫),做一些簡(jiǎn)單效果。
  • CAKeyframeAnimation(幀動(dòng)畫),做一些連續(xù)的流暢的動(dòng)畫。

三、Core Animation使用步驟及相關(guān)屬性

1、簡(jiǎn)單使用步驟
第一步:初始化一個(gè)CAAnimation對(duì)象,并設(shè)置一些動(dòng)畫相關(guān)屬性。
第二步:通過(guò)調(diào)用CALayer的addAnimation:forKey:方法增加CAAnimation對(duì)象到CALayer中,這樣就能開(kāi)始執(zhí)行動(dòng)畫了。
第三步:通過(guò)調(diào)用CALayer的removeAnimationForKey:方法可以停止CALayer中的動(dòng)畫。

2、常用屬性

duration:持續(xù)時(shí)間,默認(rèn)值是0.25秒

repeatCount:重復(fù)次數(shù),無(wú)線循環(huán)可以設(shè)置HUGE_VALF或者CGFLOAT_MAX

repeatDuration:重復(fù)時(shí)間

removeOnCompletion: 默認(rèn)為YES,代表動(dòng)畫執(zhí)行完畢后就從圖層上移除,圖形會(huì)恢復(fù)到執(zhí)行動(dòng)畫之前的狀態(tài)。如果想要圖層保持顯示動(dòng)畫執(zhí)行后的狀態(tài),那就設(shè)置為NO,同時(shí)設(shè)置fillMode為kCAFillModeForwards

fillMode:決定當(dāng)前對(duì)象在非active時(shí)間段的行為,比如動(dòng)畫開(kāi)始之前,動(dòng)畫結(jié)束之后

beginTime:可以用來(lái)設(shè)置動(dòng)畫延時(shí)執(zhí)行,若想延遲2s,就設(shè)置為CACurrentMediaTIme() + 2

CACurrentMediaTIme():圖層的當(dāng)前時(shí)間

timingFunction:速度控制函數(shù),控制動(dòng)畫運(yùn)行節(jié)奏

delegate:動(dòng)畫代理

動(dòng)畫代理能夠檢測(cè)動(dòng)畫的執(zhí)行和結(jié)束:

@interface NSObject (CAAnimationDelegate)
 - (void)animationDidStart:(CAAnimation *)anim;
 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end

3、動(dòng)畫填充模式(fillMode)

kCAFillModeForwards:當(dāng)動(dòng)畫結(jié)束后,layer會(huì)一直保持著動(dòng)畫最后的狀態(tài)

kCAFillModeBackwards:在動(dòng)畫開(kāi)始前,只需要將動(dòng)畫加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫的初始狀態(tài)并等待動(dòng)畫開(kāi)始

kCAFillModeBoth:這個(gè)其實(shí)就是上面兩個(gè)合成,動(dòng)畫加入后,開(kāi)始之前,layer便處于動(dòng)畫初始狀態(tài),動(dòng)畫結(jié)束后layer保持動(dòng)畫最后的狀態(tài)

kCAFillModeRemoved:這個(gè)是默認(rèn)值,也就是說(shuō)當(dāng)動(dòng)畫開(kāi)始前和動(dòng)畫結(jié)束后,動(dòng)畫對(duì)layer都沒(méi)有影響,動(dòng)畫結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài)

4、動(dòng)畫速度控制函數(shù)(timingFunction)

kCAMediaTimingFunctionLinear(線性):勻速,給你一個(gè)相對(duì)靜態(tài)的感覺(jué)

kCAMediaTimingFunctionEaseIn(漸進(jìn)):動(dòng)畫緩慢進(jìn)入,然后加速離開(kāi)

kCAMediaTimingFunctionEaseOut(漸出):動(dòng)畫全速進(jìn)入,然后減速的到達(dá)目的地

kCAMediaTimingFunctionEaseInEaseOut(漸進(jìn)漸出):動(dòng)畫緩慢的進(jìn)入,中間加速,然后減速的到達(dá)目的地。這個(gè)是默認(rèn)的動(dòng)畫行為。

5 、CALayer上動(dòng)畫的暫停和恢復(fù)
CALayer都是實(shí)現(xiàn)了CAMediaTiming協(xié)議(或者叫做接口)。所以layer的動(dòng)畫有一個(gè)屬性speed。如果一個(gè)layer的速度變成0.0的時(shí)候,很顯然這個(gè)動(dòng)畫就不再動(dòng)了。設(shè)置layer的speed為0時(shí),layer的動(dòng)畫暫停。speed屬性設(shè)置為任意大于0的值時(shí),動(dòng)畫恢復(fù)。

#pragma mark 暫停CALayer的動(dòng)畫
-(void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];

    // 讓CALayer的時(shí)間停止走動(dòng)
      layer.speed = 0.0;
    // 讓CALayer的時(shí)間停留在pausedTime這個(gè)時(shí)刻
    layer.timeOffset = pausedTime;
}
#pragma mark 恢復(fù)CALayer的動(dòng)畫
-(void)resumeLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = layer.timeOffset;
    // 1. 讓CALayer的時(shí)間繼續(xù)行走
      layer.speed = 1.0;
    // 2. 取消上次記錄的停留時(shí)刻
      layer.timeOffset = 0.0;
    // 3. 取消上次設(shè)置的時(shí)間
      layer.beginTime = 0.0;
    // 4. 計(jì)算暫停的時(shí)間(這里也可以用CACurrentMediaTime()-pausedTime)
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    // 5. 設(shè)置相對(duì)于父坐標(biāo)系的開(kāi)始時(shí)間(往后退timeSincePause)
      layer.beginTime = timeSincePause;
}

四、動(dòng)畫的調(diào)用方式

(1)UIView 代碼塊調(diào)用:

_demoView.frame = CGRectMake(0, 0, 50, 50);

UIView animateWithDuration:1.0f animations:^{
        _demoView.frame = CGRectMake(50, 50 50, 50);
    } completion:^(BOOL finished) {
        _demoView.frame = CGRectMake(100, 100, 50, 50);
    }];

(2)UIView [begin commit]模式

_demoView.frame = CGRectMake(0, 100, 50, 50);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0f];
_demoView.frame = CGRectMake(self.view.frame.size.width, self.view.frame.size.height/2, 50, 50);
[UIView commitAnimations];

(3)通過(guò)調(diào)用CALayer的addAnimation:forKey:

CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"position"];
anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, self.view.frame.size.height/2)];
anima.toValue = [NSValue valueWithCGPoint:CGPointMake(self.view.frame.size.width, self.view.frame.size.height/2)];
anima.duration = 1.0f;
[_demoView.layer addAnimation:anima forKey:@"positionAnimation"];

addanimation:forkey: 中的key可以設(shè)置為任意值

五、CAAnimation幾個(gè)常用的子類

1、CABaseAnimation 基礎(chǔ)動(dòng)畫
一些重要屬性

fromValue : keyPath對(duì)應(yīng)的初始值

toValue : keyPath對(duì)應(yīng)的結(jié)束值

基礎(chǔ)動(dòng)畫主要提供了對(duì)于CALayer對(duì)象中的可變屬性進(jìn)行簡(jiǎn)單動(dòng)畫的操作。比如:位移、透明度、縮放、旋轉(zhuǎn)、背景色等等。

2、CAKeyframeAnimation 關(guān)鍵幀動(dòng)畫
Keyframe顧名思義就是關(guān)鍵點(diǎn)的frame,你可以通過(guò)設(shè)定CALayer的始點(diǎn)、中間關(guān)鍵點(diǎn)、終點(diǎn)的frame,時(shí)間,動(dòng)畫會(huì)沿你設(shè)定的軌跡進(jìn)行移動(dòng) 。
一些重要屬性

path:這是一個(gè) CGPathRef 對(duì)象,默認(rèn)是空的,當(dāng)我們創(chuàng)建好CAKeyframeAnimation的實(shí)例的時(shí)候,可以通過(guò)制定一個(gè)自己定義的path來(lái)讓某一個(gè)物體按照這個(gè)路徑進(jìn)行動(dòng)畫。這個(gè)值默認(rèn)是nil,當(dāng)其被設(shè)定的時(shí)候,values 這個(gè)屬性就被覆蓋。

values:一個(gè)數(shù)組,提供了一組關(guān)鍵幀的值,當(dāng)使用path的 時(shí)候 values的值自動(dòng)被忽略。

對(duì)比基礎(chǔ)動(dòng)畫跟關(guān)鍵幀動(dòng)畫,關(guān)鍵幀動(dòng)畫引入了動(dòng)畫占比時(shí)長(zhǎng)的概念,這讓我們能控制每個(gè)關(guān)鍵幀動(dòng)畫的占用比例而不是傳入一個(gè)無(wú)意義的動(dòng)畫時(shí)長(zhǎng) —— 這讓我們的代碼更加難以理解。當(dāng)然,除了動(dòng)畫占比之外,關(guān)鍵幀動(dòng)畫的options參數(shù)也讓動(dòng)畫變得更加平滑,下面是關(guān)鍵幀特有的配置參數(shù):

UIViewKeyframeAnimationOptionCalculationModeLinear // 連續(xù)運(yùn)算模式,線性

UIViewKeyframeAnimationOptionCalculationModeDiscrete // 離散運(yùn)算模式,只顯示關(guān)鍵幀

UIViewKeyframeAnimationOptionCalculationModePaced // 均勻執(zhí)行運(yùn)算模式,線性

UIViewKeyframeAnimationOptionCalculationModeCubic // 平滑運(yùn)算模式

UIViewKeyframeAnimationOptionCalculationModeCubicPaced // 平滑均勻運(yùn)算模式

3、CAAnimationGroup 組合動(dòng)畫
Group也就是組合的意思,可以保存一組動(dòng)畫對(duì)象,將CAAnimationGroup對(duì)象加入圖層后,組中所有動(dòng)畫對(duì)象可以同時(shí)并發(fā)運(yùn)行。
其重要屬性為:

animations:用來(lái)保存一組動(dòng)畫對(duì)象的NSArray

4、CATransition 過(guò)渡動(dòng)畫
CAAnimation的子類,用于做過(guò)渡動(dòng)畫或者轉(zhuǎn)場(chǎng)動(dòng)畫,能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭?dòng)畫效果。
重要屬性:

type:動(dòng)畫過(guò)渡類型

subtype:動(dòng)畫過(guò)渡方向

startProgress:動(dòng)畫起點(diǎn)(在整體動(dòng)畫的百分比)

endProgress:動(dòng)畫終點(diǎn)(在整體動(dòng)畫的百分比)

有以下幾種type:


image.png

有以下幾種subtype:

kCATransitionFromRight 從右側(cè)進(jìn)入
kCATransitionFromLeft 從左側(cè)進(jìn)入
kCATransitionFromTop 從頂部進(jìn)入
kCATransitionFromBottom 從底部進(jìn)入
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容