目錄:
- UIView動畫
- Core Animation
- 自定義轉場動畫
- UIDynamicAnimator彈簧動畫
關于繪圖和動畫有兩種處理的方式:CPU(中央處理器)和GPU(圖形處理器)。在現代iOS設備中,都有可以運行不同軟件的可編程芯片,但是由于歷史原因,我們可以說CPU所做的工作都在軟件層面,而GPU在硬件層面。
總的來說,我們可以用軟件(使用CPU)做任何事情,但是對于圖像處理,通常用硬件會更快,因為GPU使用圖像對高度并行浮點運算做了優化。由于某些原因,我們想盡可能把屏幕渲染的工作交給硬件去處理。問題在于GPU并沒有無限制處理性能,而且一旦資源用完的話,性能就會開始下降了(即使CPU并沒有完全占用)。
1. UIView動畫
在UIView類中共有三個類目(Category)用于實現動畫功能,分為UIViewAnimation、UIViewAnimationWithBlocks以及UIViewKeyframeAnimations,他們是對核心動畫(Core Animation)的封裝,可以讓我們不進行任何繪畫等復雜操作的前提下實現大部分動畫需求
UIView動畫就是利用UIView的API來實現動畫效果。而利用UIView API也可以分為兩種,一種block形式,一種多API組合。
一、一般形式的UIView動畫
#pragma mark - 一般形式的UIView動畫
- (void)baseViewAnimation
{
[UIView beginAnimations:@"centerAnimation" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationWillStartSelector:@selector(animationWillStart)];
[UIView setAnimationDidStopSelector:@selector(animationDidStop)];
self.testView.center = CGPointMake(K_width/2, 64);
[UIView commitAnimations];
}
- (void)animationWillStart
{
self.testView.transform = CGAffineTransformMakeScale(0.2, 0.2);
}
- (void)animationDidStop
{
self.testView.transform = CGAffineTransformIdentity;;
}
二、block形式的UIView動畫
在animations block中只能修改UIView的部分屬性,產生動畫效果。而可以產生動畫效果的屬性,蘋果在其注釋中都有標記 animatable。
1. 最簡單的UIView動畫API
第一個參數是動畫執行時長(單位:秒);第二個參數就是動畫的block,屬性變化信息的最終值。
[UIView animateWithDuration:3.0 animations:^{
self.testView.frame = CGRectMake(50, 50, 100, 100);
}];
2. 比方法1多了一個延遲時間(單位:秒)和動畫類型
延遲時間是表示多久之后執行該動畫,動畫執行類型有樣式,比如速度先快后慢,開始快中間慢結束時再快,勻速等等。可以移除設置不同的枚舉值來比較。
#pragma mark - block形式的UIView動畫
- (void)blockAnimation_1
{
[UIView animateWithDuration:3.0 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.testView.center = CGPointMake(K_width/2, K_height-self.testView.bounds.size.height/2);
} completion:^(BOOL finished) {
[self.testView removeFromSuperview];
}];
}
3. 彈性動畫
像橡皮筋一樣,將試圖改變至屬性所設置的值后,會有一個回彈效果。根據設置的初速度和阻尼系數慢慢停止,最終停留在屬性所設置的值的狀態。
相比于方法2,多了一個damping阻尼系數和初速度
- (void)blockAnimation_2 // 彈性動畫
{
/*
usingSpringWithDamping: 震動效果,取值范圍在0.0~1.0, 取值越小,震蕩幅度越大
initialSpringVelocity:初始速度,數值越大初始速度越快。確定了在動畫結束之前運動的速度。一般情況下都是設置為0。設值舉個例子來說,如果想要移動的距離為200pt,移動速度為100pt/s,就需要設置為0.5。
options:動畫的過渡效果
*/
[UIView animateWithDuration:2 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.testView.center = CGPointMake(K_width/2, K_height-self.testView.bounds.size.height/2-10);
} completion:^(BOOL finished) {
}];
}
4. 關鍵幀動畫
UIView動畫現在只支持屬性關鍵幀動畫,不支持路徑關鍵幀動畫
[UIView animateKeyframesWithDuration:(NSTimeInterval)//動畫持續時間
delay:(NSTimeInterval)//動畫延遲執行的時間
options:(UIViewKeyframeAnimationOptions)//動畫的過渡效果
animations:^{
//執行的關鍵幀動畫
}
completion:^(BOOL finished) {
//動畫執行完畢后的操作
}];
增加關鍵幀的方法:
[UIView addKeyframeWithRelativeStartTime:(double)//動畫開始的時間(占總時間的比例)
relativeDuration:(double) //動畫持續時間(占總時間的比例)
animations:^{
//執行的動畫
}];
具體實現方法
- (void)blockAnimation_3 // 關鍵幀動畫
{
[UIView animateKeyframesWithDuration:5 delay:0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionCurveLinear animations:^{
//第一個關鍵幀:從0秒開始持續50%的時間,也就是5.0*0.5=2.5秒
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
self.testView.center = CGPointMake(K_width/2, K_height-self.testView.bounds.size.height/2-10);
}];
//第二個關鍵幀:從50%時間開始持續25%的時間,也就是5.0*0.25=1.25秒
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
self.testView.center = CGPointMake(0, 0);
}];
//第三個關鍵幀:從75%時間開始持續25%的時間,也就是5.0*0.25=1.25秒
[UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.25 animations:^{
self.testView.center = CGPointMake(K_width/2, K_height/2);
}];
} completion:^(BOOL finished) {
}];
}
關鍵幀動畫的options多了一些選擇
/* 動畫模式選擇,選擇一個 */
UIViewKeyframeAnimationOptionCalculationModeLinear/*< 連續運算模式 */
UIViewKeyframeAnimationOptionCalculationModeDiscreter/*< 離散運算模式 */
UIViewKeyframeAnimationOptionCalculationModePacedr/*< 均勻執行運算模式 */
UIViewKeyframeAnimationOptionCalculationModeCubicr/*< 平滑運算模式 */
UIViewKeyframeAnimationOptionCalculationModeCubicPacedr/*< 平滑均勻運算模式 */
5. 轉場動畫
第一種:單個視圖的過渡效果
- (void)transitionWithView_4 // 轉場動畫
{
/*
以上方式可以在改變視圖的屬性時產生動畫,如果視圖添加或者移除的時候想要添加動畫,就要用到下面的方式了
*/
UIViewAnimationOptions option = UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft;
[UIView transitionWithView:self.imageview duration:10.0 options:option animations:^{
UIImage *image = [UIImage imageNamed:@"maskImage"];
self.imageview.image = image;
} completion:^(BOOL finished) {
}];
}
轉場動畫options多了一些選擇:
/* 轉場類型 */
UIViewAnimationOptionTransitionNone/*< 沒有轉場動畫效果 */
UIViewAnimationOptionTransitionFlipFromLeft/*< 從左側翻轉效果 */
UIViewAnimationOptionTransitionFlipFromRight/*< 從右側翻轉效果 */
UIViewAnimationOptionTransitionCurlUp/*< 向后翻頁的動畫過渡效果 */
UIViewAnimationOptionTransitionCurlDown/*< 向前翻頁的動畫過渡效果 */
UIViewAnimationOptionTransitionCrossDissolve/*< 溶解消失效果 */
UIViewAnimationOptionTransitionFlipFromTop/*< 從上方翻轉效果 */
UIViewAnimationOptionTransitionFlipFromBottom/*< 從底部翻轉效果 */
第二種:兩個視圖之間轉場可以使用,從舊視圖轉到新視圖的動畫效果
默認情況,轉出的視圖會從父視圖移除,轉入后重新添加在該動畫過程中,fromView 會從父視圖中移除,并講 toView 添加到父視圖中,注意轉場動畫的作用對象是父視圖(過渡效果體現在父視圖上)。
- (void)transitionWithView_5 // 轉場動畫
{
/*
這是一個便捷的視圖過渡 API,在動畫過程中,首先將 fromView 從父視圖中刪除,然后將 toView 添加,就是做了一個替換操作。
在需要視圖更改時,這個將變得特別有用。
*/
UIViewAnimationOptions option = UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft;
[UIView transitionFromView:self.testView toView:self.imageview duration:5 options:option completion:^(BOOL finished) {
}];
}
調用該方法相當于執行下面兩句代碼:
[fromView.superview addSubview:toView];
[fromView removeFromSuperview];
2. Core Animation
定義:
Core Animation,中文翻譯為核心動畫,它是一組非常強大的動畫處理API,使用它能做出非常炫麗的動畫效果,而且往往是事半功倍。也就是說,使用少量的代碼就可以實現非常強大的功能。
Core Animation 是跨平臺的,可以用在Mac OS X 和iOS 平臺。
Core Animation 的動畫執行過程都是在后臺操作的,不會阻塞主線程。不阻塞主線程,可以理解為在執行動畫的時候還能點擊(按鈕)。
要注意的是,Core Animation 是直接作用在 CALayer 上的,并非UIView,iOS 的 UIView 背后都有一個對應的 CALayer。對 UIView 的修改實際上都是對背后 CALayer 的修改。
當 CALayer 在背后支持一個 UIView 的時候,UIView 就是它的 delegate。即,UIView 是 CALayer 的CALayerDelegate。
即 Core Animation 不改變 UIView 的 Frame 屬性,也就是說并不改變 UIView 的實際位置。
圖層樹和模型樹
CALayer 的同一個屬性值,會分別保存在模型層 modelLayer ,和展現層 presentationLayer 中。當我們修改屬性值時,是修改的模型層的數值,動畫時系統根據模型層的變化,生成的過渡值,是保存在展現層中的。
在CALayer 的對象里能直接訪問到這兩層的信息。而CALayer 的底層實現實際不止這兩層,但我們現在討論動畫的時候,可以只關心這兩層。
在整個動畫過程中,呈現出來的過程是這樣的:
動畫前,顯示模型層的當前值;
動畫開始,切換顯示展現層的值;
動畫過程中,展現層的值根據時間變化,我們看到的實際是展現層的值在變化;
動畫結束,切換回顯示模型層的值,此時模型層的值應被修改為動畫結束時的值。
由于在動畫過程中,修改的只是展現層的值,模型層的值并沒有改變,所以Core Animation 并不修改 UIView 的實際位置。(如果要修改UIView 的實際位置,則要手動修改 UIView 的 Frame)
UIKit動畫和Core Animation
UIKit實現的動畫效果往往都可以滿足你對動畫的需求,而且實現代碼非常簡單,就像Core Animation的隱式動畫一樣,只需要在UIKit事務中修改相應可動畫屬性即可,所以,一般情況下UIKit動畫是你優先選擇的方式,但這里有一個誤區,有很多人在講述iOS動畫的時候,會把UIKit動畫和Core Animation動畫定義成兩種完全不同的處理方式,并且認為Core Animation動畫的性能會更優一些,但事實并非如此,UIKit動畫和Core Animation動畫是相關連的。
UIKit雖然提供了非常簡便的API來實現動畫,但UIKit動畫畢竟是Core Animation動畫的一個抽象物,能提供的效果還是很有限的。
UIKit動畫其內部實現是Core Animation動畫。UIView對象的rootlayer的隱式動畫是默認關閉的。
顯式動畫和隱式動畫
Core Animation動畫有兩種形式,分別是顯式動畫和隱式動畫,但不管以哪種形式實現動畫,都是基于CAAnimation來實現的,所以這兩種動畫形式的主要差異在于,是否顯式創建CAAnimation對象來實現動畫,當然它們還存在其它的差異,例如,隱式動畫是基于CABasicAnimation對來實現的,而顯式動畫可以有更多的選擇,可以是CABasicAnimation,CAKeyframeAnimation,CATransition等。
對于獨立CALayer而言,隱式動畫是默認開啟的,只需要更改可動畫屬性就會觸發隱式動畫,但對于UIView的rootlayer而言,隱式動畫是默認關閉的。
雖然隱式動畫的大部份參數由CATransaction來決定,顯式創建CATransaction常常被用于關閉隱式動畫(獨立的CALayer對象默認開啟隱式動畫,需要手動關閉)和調整動畫的時間。
Core Animation的動畫執行過程都是在后臺操作的,不會阻塞主線程。Core Animation是直接作用在CALayer上的,并非UIView。
CAAnimation注意要點:
- 能用的動畫類只有4個子類:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup;
- CAMediaTiming是一個協議(protocol),CAMediaTiming媒體時間類協議解析:
1.beginTime 動畫開始的時間默認為0;
2.duration 動畫的持續時間,默認為0 ,持續時間受速度的影響 實際動畫完成時間 = 持續時間/速度;
3.speed 動畫的播放速度 ,默認為1 ,速度設置為0 ,可以暫停動畫。如果speed=2 , duration =60 那么動畫真正播放完成的時間 30秒;
4.timeOffset 動畫播放時間的偏移量;
5.repeatCount 動畫的循環次數 默認是0 只播放一次;
6.repeatDuration 動畫循環的持續時間,
repeatCount/repeatDuration 只能設置其中的一個屬性;
7.autoreverses 是否以動畫的形式返回 返回到播放之前的狀態;
8.fillMode 動畫填充模式,設置當前對象在非活動時間段的狀態,
要想fillMode有效 需設置removedOnCompletion = NO;
kCAFillModeForwards 當動畫結束后,layer會一直保持著動畫最后的狀態
kCAFillModeBackwards 立即進入動畫的初始狀態并等待動畫開始
kCAFillModeBoth 動畫加入后開始之前 layer處于動畫初始狀態 動畫結束后layer保持動畫最后的狀態
kCAFillModeRemoved 默認值 動畫結束后 layer會恢復到之前的狀態
CAAnimation動畫屬性方法介紹:
- 初始化的方法 animation
-
timingFunction 速度控制函數,控制動畫運行的節奏
timingFunction的初始化方法: functionWithName:
kCAMediaTimingFunctionLinear 線性,勻速
kCAMediaTimingFunctionEaseIn 慢進后快
kCAMediaTimingFunctionEaseOut 快進后慢
kCAMediaTimingFunctionEaseInEaseOut 先慢進后快再慢出
kCAMediaTimingFunctionDefault 實際效果是動畫中間比較快
- removedOnCompletion 完成動畫的時候 是否移除動畫效果 默認為YES
- 代理方法:
-(void)animationDidStart:(CAAnimation *)anim
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
CAAnimation子類:
- CAAnaimation和CAPropertyAnimation是個抽象類,不具備動畫效 果,必須用它們的子類才有動畫效果;
- CABasicAnimation基本動畫,做一些簡單效果;
- CAKeyframeAnimation幀動畫,做一些連續的流暢的動畫;
- CAAnimationGroup是個動畫組,可以同時進行縮放,旋轉。
- CATransition是轉場動畫,界面之間跳轉都可以用轉場動畫。
1. CABasicAnimation 基礎動畫
CABasicAnimation用來創建基于兩個狀態的動畫,你只需要給出兩個狀態,一個初始狀態一個終止狀態,系統自動為你將中間的動畫補全。
通過設定起始點,終點,時間,動畫會沿著你這設定點進行移動。可以看做特殊的CAKeyFrameAnimation.
CABasicAnimation動畫主要是設置某個動畫屬性的初始值fromValue和結束值toValue,來產生動畫效果。
創建CABasicAnimation 的方法,但是在最新的apple開發文檔沒有查到path到底有哪些,網上搜羅了一下,并猜測path跟layer中的屬性字段是一致的如background。
基于CAPropertyAnimation的屬性動畫,可以更改屬性,二級屬性也可以去做動畫。
| path | 用途
| -------------
| rotaion.x | 旋轉,弧度,X軸
| rotaion.y | 旋轉,弧度,Y軸
| rotaion.z | 旋轉,弧度,Z軸
| rotaion | 旋轉,弧度,Z軸,完全等同于rotation.z
| scale.x | 縮放,X軸
| scale.y | 縮放,Y軸
| scale.z | 縮放,Z軸
| scale | 縮放,XYZ軸
| translation.x | 移動,X軸
| translation.y | 移動,Y軸
| translation.z | 移動,Z軸
| translation | 移動,XY軸,value值為NSSize或者CGSize類型
| opacity等 | zPosition、frame、backgroundColor、cornerRadius類似的layer中的各種屬性
Animation的幾個屬性:
animationWithKeyPath:動畫的創建使用animationWithKeyPath: 因為使用的keyPath所以動畫屬性或者其結構體中元素都可以產生動畫;
duration: 動畫的時長;
fromValue和toValue: 是CABasicAnimation的屬性,都是id類型的,所以要將基本類型包裝成對象;
removedOnCompletion: 決定動畫執行完之后是否將該動畫的影響移除,默認是YES,則layer回到動畫前的狀態;是否在播放完成后移除。這是一個非常重要的屬性,有的時候我們希望動畫播放完成,但是保留最終的播放效果是,這個屬性一定要改為NO,否則無效。
fillMode: 是個枚舉值(四種),當removedOnCompletion設置為NO之后才會起作用。可以設置layer是保持動畫開始前的狀態還是動畫結束后的狀態,或是其他的;
autoreverses: 表示動畫結束后是否 backwards(回退) 到動畫開始前的狀態。可與上面兩個屬性組合出不同效果。
timingFunction: 動畫的運動是勻速線性的還是先快后慢等,類似UIView動畫的opitions。另外,CAMediaTimingFunction 方法可以自定義。
delegate 代理:兩個動畫代理方法:
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
添加/移除動畫方法
給某個layer添加動畫
- (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)key;
與之對應的移除某個動畫是
- (void)removeAnimationForKey:(NSString *)key;
#pragma mark - CABasicAnimation-基礎動畫:位移、透明度、縮放、旋轉
/**
* 透明度動畫
*/
-(void)opacityAniamtion{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"opacity"];
//fromValue和toValue都是id類型的,所以要將基本類型包裝成對象
anima.fromValue = [NSNumber numberWithFloat:1.0f];
anima.toValue = [NSNumber numberWithFloat:0.2f];
anima.duration = 1.0f; //動畫的時長
//決定動畫執行完之后是否將該動畫的影響移除,默認是YES,則layer回到動畫前的狀態
anima.removedOnCompletion = NO;
//是個枚舉值(四種),當removedOnCompletion設置為NO之后才會起作用。可以設置layer是保持動畫開始前的狀態還是動畫結束后的狀態,或是其他的
anima.fillMode = kCAFillModeForwards;
//表示動畫結束后是否 backwards(回退) 到動畫開始前的狀態。可與上面兩個屬性組合出不同效果。
//anima.autoreverses = YES;
//動畫的運動是勻速線性的還是先快后慢等,類似UIView動畫的opitions。另外,CAMediaTimingFunction 方法可以自定義。
anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anima.delegate = self;//設置代理,可以檢測動畫的開始和結束
[self.testView.layer addAnimation:anima forKey:@"opacityAniamtion"];
}
/**
* 縮放動畫
*/
-(void)scaleAnimation{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform.scale"];//同上
anima.toValue = [NSNumber numberWithFloat:2.0f];
anima.duration = 1.0f;
anima.removedOnCompletion = NO;
anima.fillMode = kCAFillModeForwards;
[self.testView.layer addAnimation:anima forKey:@"scaleAnimation"];
}
/**
* 旋轉動畫
*/
-(void)rotateAnimation{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];//繞著z軸為矢量,進行旋轉(@"transform.rotation.z"==@@"transform.rotation")
anima.toValue = [NSNumber numberWithFloat:3*M_PI];
anima.duration = 1.0f;
[self.testView.layer addAnimation:anima forKey:@"rotateAnimation"];
}
/**
* 背景色變化動畫
*/
-(void)backgroundAnimation{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
anima.toValue =(id) [UIColor greenColor].CGColor;
anima.duration = 1.0f;
[self.testView.layer addAnimation:anima forKey:@"backgroundAnimation"];
}
2. CAKeyframeAnimation 關鍵幀動畫
Keyframe顧名思義就是關鍵點的frame,你可以通過設定CALayer的始點、中間關鍵點、終點的frame,時間,動畫會沿你設定的軌跡進行移動 CAKeyframeAnimation 的一些比較重要的屬性。所以CAKeyframeAnimation也是根據屬性展示動畫的,他與CABasicAnimation的不同點在于他可以指定多個狀態,不局限于始末狀態,這樣你的動畫將更加靈活。
CAKeyframeAnimation我們一般稱為關鍵幀動畫,主要是利用其values屬性,設置多個關鍵幀屬性值,來產生動畫。
對比UIView動畫跟關鍵幀動畫,關鍵幀動畫引入了動畫占比時長的概念,這讓我們能控制每個關鍵幀動畫的占用比例而不是傳入一個無意義的動畫時長 —— 這讓我們的代碼更加難以理解。當然,除了動畫占比之外,關鍵幀動畫的options參數也讓動畫變得更加平滑。
2.1. path
這是一個 CGPathRef 對象,默認是空的,當我們創建好CAKeyframeAnimation的實例的時候,可以通過制定一個自己定義的path來讓某一個物體按照這個路徑進行動畫。這個值默認是nil,當其被設定的時候values 這個屬性就被覆蓋。
/**
* path動畫
*/
-(void)pathAnimation{
CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"position"];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(SCREEN_WIDTH/2-100, SCREEN_HEIGHT/2-100, 200, 200)];
anima.path = path.CGPath;
anima.duration = 2.0f;
anima.removedOnCompletion = NO;
anima.fillMode = kCAFillModeForwards;
[_demoView.layer addAnimation:anima forKey:@"pathAnimation"];
}
2.2. values
一個數組,提供了一組關鍵幀的值,當使用path的 時候 values的值自動被忽略。
-(void)keyframeAnimation{
CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
keyAnimation.duration = 1.0f;
//CAAnimation類的屬性,可以設置動畫延遲多久執行,示例代碼是延遲1秒執行。
keyAnimation.beginTime = CACurrentMediaTime() + 1.0;
CATransform3D transform1 = CATransform3DMakeScale(1.5, 1.5, 0);
CATransform3D transform2 = CATransform3DMakeScale(0.8, 0.8, 0);
CATransform3D transform3 = CATransform3DMakeScale(3, 3, 0);
//是CAKeyframeAnimation的屬性,設置keyPath屬性在幾個關鍵幀的值,也是id類型的。
keyAnimation.values = @[[NSValue valueWithCATransform3D:transform1],[NSValue valueWithCATransform3D:transform2],[NSValue valueWithCATransform3D:transform3]];
//是CAKeyframeAnimation的屬性,每個值對應相應關鍵幀的時間比例值。keyTimes屬性指定的是當前狀態節點到初始狀態節點的時間占動畫總時長的比例。若果不設置keyTimes則勻速播放
keyAnimation.keyTimes = @[@0,@0.5,@1];
//是CAKeyframeAnimation的屬性,對應每個動畫段的動畫過渡情況;而timingFunction是CAAnimation的屬性。
keyAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
keyAnimation.removedOnCompletion = NO;
keyAnimation.fillMode = kCAFillModeForwards;
[self.testView.layer addAnimation:keyAnimation forKey:nil];
}
3. CAAnimationGroup 組合動畫
Group也就是組合的意思,可以保存一組動畫對象,CAAnimationGroup的animations中可以放其他任何動畫類(包括CAAnimationGroup),將CAAnimationGroup對象加入圖層后,組中所有動畫對象可以同時并發運行。
animations屬性:用來保存一組動畫對象的NSArray
注意:
- animations里的單個動畫,當單個動畫設置了duration之后動畫可能會有不同,一般里面不設置,在最外層設置group的duration即可。
- 默認情況下,一個layer設定了很多動畫,他們都會同時執行,而且是順序執行,也可以通過設置動畫對象的beginTime屬性來更改動畫的開始時間
-(void)groupAnimation1{
// //位移動畫
CAKeyframeAnimation *anima1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-50)];
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2-50)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2+50)];
NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2+50)];
NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2-50)];
NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50)];
anima1.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil];
//縮放動畫
CABasicAnimation *anima2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
anima2.fromValue = [NSNumber numberWithFloat:0.8f];
anima2.toValue = [NSNumber numberWithFloat:2.0f];
//旋轉動畫
CABasicAnimation *anima3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
anima3.toValue = [NSNumber numberWithFloat:M_PI*4];
//組動畫
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.animations = [NSArray arrayWithObjects:anima1,anima2,anima3, nil];
groupAnimation.duration = 4.0f;
[_demoView.layer addAnimation:groupAnimation forKey:@"groupAnimation"];
}
4. CATransition 系統封裝的過渡動畫
CATransition動畫就是動畫效果和方向的結合,以下為重要屬性
type:動畫過渡類型
Apple 官方的SDK其實只提供了四種過渡效果,都支持方向設置:
kCATransitionFade 淡出效果
kCATransitionMoveIn 新視圖移動到舊視圖上
kCATransitionPush 新視圖推出舊視圖
kCATransitionReveal 移開舊視圖顯示新視圖
私有API提供了其他很多非常炫的過渡動畫,其中部分支持方向設置,比如:
@"cube":立方體翻轉效果
@"suckEffect":收縮效果
@"oglFlip":翻轉效果
@"rippleEffect":水滴波紋效果
@"pageCurl":向上翻頁效果
@"pageUnCurl":向下翻頁效果
@"cameraIrisHollowOpen":攝像頭打開效果
@"cameraIrisHollowClose":攝像頭關閉效果
注意:私有api,不建議開發者們使用。因為蘋果公司不提供維護,并且有可能造成你的app審核不通過。
subtype:動畫過渡方向
kCATransitionFromRight 從右側進入
kCATransitionFromLeft 從左側進入
kCATransitionFromTop 從頂部進入
kCATransitionFromBottom 從底部進入
startProgress:動畫起點(在整體動畫的百分比)
endProgress:動畫終點(在整體動畫的百分比)
寫法一
#pragma mark - CATransition:轉場動畫:淡入淡出、推擠、解開、覆蓋
-(void)transitionAnimation
{
/*
什么是轉場動畫?
就是從一個場景轉換到另外一個場景,像導航控制器的push效果,就是一個轉場。能為層提供移除屏幕和移入屏幕的動畫效果
CATransition通常用于通過CALayer控制UIView內子控件的過渡動畫,比如刪除子控件,添加子控件,切換兩個子控件等。
imageView切換圖片,控制器的push或modal,UIView對象調用exchangeSubviewAtIndex:WithIndex:方法的時候可以出發轉場動畫.
基本使用
創建CATransition對象。
為CATransition設置type和subtype兩個屬性,type指定動畫類型,subtype指定動畫移動方向(有些動畫是固定方向,指定subtype無效)。
如果不需要動畫執行整個過程(動畫執行到中間部分就停止),可以指定startProgress,endProgress屬性。
調用UIView的layer屬性的addAnimation: forKey:方法控制該UIView內子控件的過渡動畫。
動畫類型:
CATransition的type有以下幾個值
kCATransitionFade 漸變
kCATransitionMoveIn 覆蓋
kCATransitionPush 推出
kCATransitionReveal 揭開
除此之外,該type還支持如下私有動畫
cube 立方體旋轉
suckEffect 收縮動畫
oglFlip 翻轉
rippleEffect 水波動畫
pageCurl 頁面揭開
pageUnCurl 放下頁面
cemeraIrisHollowOpen 鏡頭打開
cameraIrisHollowClose 鏡頭關閉
CATransition的subtype屬性用于控制動畫方向,支持如下值
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom
*/
//創建一個轉場動畫
CATransition *animation = [CATransition animation];
animation.beginTime = CACurrentMediaTime() + 1.0;
animation.duration = 5;
//設置轉場類型
//animation.type = kCATransitionMoveIn;
animation.type = @"oglFlip";
//設置轉場的方向
animation.subtype = kCATransitionFromTop;
//設置動畫開始的位置
//animation.startProgress = 0.5;
//設置動畫結束的位置
//animation.endProgress = 0.8;
UIImage *image = [UIImage imageNamed:@"maskImage"];
self.imageview.image = image;
//添加動畫
[self.imageview.layer addAnimation:animation forKey:@"transitionAnimation"];
}
寫法二
-(void)test
{
[UIView beginAnimations:@"animationID" context:nil];
[UIView setAnimationDuration:0.5f]; //動畫時長
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES]; //給視圖添加過渡效果
//在這里寫你的代碼.
[UIView commitAnimations]; //提交動畫
}
#pragma UIView實現動畫
- (void) animationWithView : (UIView *)view WithAnimationTransition : (UIViewAnimationTransition) transition
{
[UIView animateWithDuration:DURATION animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:transition forView:view cache:YES];
}];
}
3. 自定義轉場動畫
非交互式的轉場動畫
目前為止,官方支持以下幾種方式的自定義轉場:
在 UINavigationController 中 push 和 pop;
在 UITabBarController 中切換 Tab;
Modal 轉場:presentation 和 dismissal,俗稱視圖控制器的模態顯示和消失,僅限于modalPresentationStyle屬性為 UIModalPresentationFullScreen 或 UIModalPresentationCustom 這兩種模式;
UICollectionViewController 的布局轉場:UICollectionViewController 與 UINavigationController 結合的轉場方式,實現很簡單。
轉場代理(Transition Delegate)
這個協議要求我們實現兩個方法,其中一個定義了動畫的持續時間:
另一個方法描述整個動畫的執行效果:
方法中獲取 transition context,從 transition context 中得到了需要做轉場的兩個 view controller,然后可以使用最簡單的 UIView animation 來實現轉場動畫
交互式的轉場動畫