移動開發(IOS) – 動畫

移動開發(IOS) – 動畫

By docoder in 博客學習 on 2014/07/03

animation

1.CALayer 

1.1.學習核心動畫之前,需要先理解 CALayer,因爲核心動畫操作的對象不是 UIView,而是 CALayer 。

1.2.CALayer 是核心動畫的基礎,可以做圓角、陰影、邊框等效果 。

1.3.每個 UIView 內部都有一個 Layer 的屬性 。

1.4.在實現核心動畫時,本質上是將 CALayer 中的內容轉換成位圖,從而便於圖形硬件的操縱 。

1.5.在 UIView 中 CALayer 只是一個類聲明,因此需要添加 QuartzCore 框架 。

1.6.UIKit 框架只能應用在 iOS 而不能用於 Mac,但是 Quartz 2D 是可以跨平臺的,因此在使用顏色時,不能直接使用 UIColor而需要將顏色轉成 CGColor 。

1.7.修改圖層相當於修改UIView屬性,即修改了界面屬性 。

1.8.形變屬性既可以用形變函數指定,也可以用keyPath指定 。

1.9.創建視圖對象時,視圖會自己創建一個層,視圖在繪圖(如 drawRect: )時,會將內容畫在自己的層上。當視圖在層上完成繪圖後,系統會將圖層拷貝至屏幕。每個視圖都有一個層,而每個圖層又可以有多個子層 。

1.10.Layer 的設計目的不是爲了取代視圖,因此不能基於 CALayer 創建一個獨立的可視化組件 。

1.11.Layer 的設計目的是提供視圖的基本可視內容,從而提高動畫的執行效率 。

1.12.除提供可視內容外,Layer 不負責視圖的事件響應、內容繪製等工作,同時 Layer 不能參與到響應者鏈條中 。

1.13.CALayer 層次結構:

CALayer

1.14.CALayer 的使用說明

1.14.1.通過 UIView 的 layer 屬性可以拿到對應的根層,這個層不允許重新創建,但可以往層裏面添加子層(調用 CALayer 的 addSublayer )。

1.14.2.要具體使用CALayer,需要引入<QuartzCore/QuartzCore.h>。

1.14.3.獲取當前圖層或使用靜態方法 layer 初始化 CALayer 後,可以設置以下屬性:


bounds 寬度和高度
position 位置(默認指中心點,具體由 anchorPoint 決定)
anchorPoint 錨點( x,y 的範圍都是 0-1 ),決定了 position 的含義
backgroundColor 背景顏色( CGColorRef 類型)
borderColor 邊框顏色( CGColorRef 類型)
borderWidth 邊框寬度
cornerRadius 圓角半徑
contents 內容(比如設置爲圖片 CGImageRef )
transform 旋轉、縮放、平移

1.14.4.雖然 CALayer 可以使用 frame,但最好還是使用 bounds 和 position。爲層設置動畫時,用 bounds 和 position 會方便一點。

1.14.5.注意錨點和位置的關係,以及在旋轉轉換時對圖層的影響。

1.14.6.UIView 有一個 addSubview 方法,而 layer 有一個 addSubLayer 方法。

1.14.7.CALayer 中使用 CGColorRef 和 CGImageRef 的數據類型,而不用 UIColor 和 UIImage 。

1.14.8.可以通過 UIKi t對象的特定方法,可以得到 Core Graphics 對象,如 UIImage 的 CGImage 方法和 UIColor 的 CGColor 方法。

1.15.CALayer 的隱式動畫屬性

1.15.1.每一個 UIView 內部都默認關聯着一個 CALayer,稱這個 Layer 爲 Root Layer。所有的非 Root Layer 都存在着隱式動畫,隱式動畫的默認時長爲 1/4 秒。

1.15.2.當修改非 Root Layer 的部分屬性時,相應的修改會自動產生動畫效果,能執行隱式動畫的屬性被稱爲“可動畫屬性”,諸如:


bounds 縮放動畫
position 平移動畫
opacity 淡入淡出動畫(改變透明度)
 … …  … …

1.15.3.如果要關閉默認的動畫效果,可以通過動畫事務方法實現:

1
2
3
4
[CATransaction begin];
[CATransaction setDisableActions:YES];
// ...
[CATransaction commit];

1.16.在 CALayer 上繪圖

1.16.1.創建一個 CALayer 的子類,然後覆蓋 drawInContext: 方法,可以使用 Quartz2D API 在其中進行繪圖。

1.16.2.設置 CALayer 的 delegate,然後讓 delegate 實現 drawLayer:inContext: 方法進行繪圖。

1.16.3.不能再將 UIView 設置爲這個 CALayer 的 delegate,因爲 UIView 對象已經是內部層的 delegate,再次設置會出問題。

1.16.4.無論使用哪種方法,都必須向層發送 setNeedsDisplay 消息,以觸發相應繪圖方法的調用。

1.17.CALayer、 UIView 以及上下文之間的關係:

1.17.1.當 UIView 收到 setNeedsDisplay 消息時,CALayer 會準備好一個 CGContextRef,然後向它的 delegate 即 UIView,發送消息,並且傳入已經準備好的 CGContextRef 對象。UIView 在 drawLayer:inContext: 方法中會調用自己的 drawRect: 方法。

1.17.2.平時在 drawRect: 中通過 UIGraphicsGetCurrentContext() 獲取的就是由 CALayer 傳入的 CGContextRef 對象,在 drawRect: 中完成的所有繪圖都會填入 CALayer 的 CGContextRef 中,然後被拷貝至屏幕。

1.17.3. CALayer 的 CGContextRef 用的是位圖上下文( Bitmap Graphics Context )。

1.18.在實現核心動畫時,本質上是將 CALayer 中的內容轉換成位圖,從而便於圖形硬件的操縱。

2.Core Animation

2.1.Core Animation 是跨平臺的,支持 iOS 環境和 Mac OS X 環境。

2.2.使用它需要先添加 QuartzCore.framework 和引入對應的框架 <QuartzCore/QuartzCore.h> 。

2.3.開發步驟:

2.3.1.初始化一個動畫對象 ( CAAnimation ) 並設置一些動畫相關屬性。

2.3.2.CALayer 中很多屬性都可以通過 CAAnimation 實現動畫效果,包括:opacity、 position、 transform、 bounds、 contents 等( 可以在 API 文檔中搜索: CALayer Animatable Properties )。

2.3.3.添加動畫對象到層( CALayer )中,開始執行動畫。

2.3.4.通過調用 CALayer 的 addAnimation:forKey 增加動畫到層( CALayer )中,這樣就能觸發動畫了。通過調用 removeAnimationForKey 可以停止層中的動畫。

2.3.5.Core Animation 的動畫執行過程都是在後臺操作的,不會阻塞主線程。

3.CAAnimation

3.1.CAAnimation 繼承結構

CAAnimation

3.2.CAAnimation 是所有動畫對象的父類,負責控制動畫的持續時間和速度,是個抽象類,不能直接使用,應該使用它具體的子類。

3.3.屬性說明:


duration (來自CAMediaTiming協議的屬性)動畫的持續時間
repeatCount (來自CAMediaTiming協議的屬性)重複次數,無限循環可以設置 HUGE_VALF 或者 MAXFLOAT
repeatDuration (來自CAMediaTiming協議的屬性)重複時間
removedOnCompletion 默認爲 YES,代表動畫執行完畢後就從圖層上移除,圖形會恢復到動畫執行前的狀態。如果想讓圖層保持顯示動畫執行後的狀態,那就設置爲 NO,不過還要設置 fillMode 爲 kCAFillModeForwards
fillMode (來自CAMediaTiming協議的屬性)決定當前對象在非active時間段的行爲。比如動畫開始之前或者動畫結束之後
beginTime (來自CAMediaTiming協議的屬性)可以用來設置動畫延遲執行時間,若想延遲 2s,就設置爲 CACurrentMediaTime()+2 , CACurrentMediaTime() 爲圖層的當前時間
timingFunction 速度控制函數,控制動畫運行的節奏
delegate 動畫代理

3.4.CAAnimation 的動畫填充模式,fillMode 屬性值(要想 fillMode 有效,最好設置 removedOnCompletion = NO ):

3.4.1.kCAFillModeRemoved 這個是默認值,也就是說當動畫開始前和動畫結束後,動畫對 layer 都沒有影響,動畫結束後,layer 會恢復到之前的狀態。

3.4.2.kCAFillModeForwards 當動畫結束後,layer 會一直保持着動畫最後的狀態 。

3.4.3.kCAFillModeBackwards 在動畫開始前,只需要將動畫加入了一個 layer,layer 便立即進入動畫的初始狀態並等待動畫開始。

3.4.4.kCAFillModeBoth 這個其實就是上面兩個的合成.動畫加入後開始之前,layer 便處於動畫初始狀態,動畫結束後 layer 保持動畫最後的狀態。

3.5.CAAnimation 的速度控制函數( CAMediaTimingFunction ):

3.5.1. kCAMediaTimingFunctionLinear (線性):勻速,給你一個相對靜態的感覺。

3.5.2. kCAMediaTimingFunctionEaseIn (漸進):動畫緩慢進入,然後加速離開。

3.5.3. kCAMediaTimingFunctionEaseOut (漸出):動畫全速進入,然後減速的到達目的地。

3.5.4. kCAMediaTimingFunctionEaseInEaseOut (漸進漸出):動畫緩慢的進入,中間加速,然後減速的到達目的地。這個是默認的動畫行爲。

3.6.CAAnimation 動畫代理方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@interface NSObject (CAAnimationDelegate)
 
/* Called when the animation begins its active duration. */
 
- (void)animationDidStart:(CAAnimation *)anim;
 
/* Called when the animation either completes its active duration or
 * is removed from the object it is attached to (i.e. the layer). 'flag'
 * is true if the animation reached the end of its active duration
 * without being removed. */
 
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
 
@end

3.7.CALayer上動畫的暫停和恢復:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#pragma mark 暫停CALayer的動畫
-(void)pauseLayer:(CALayer*)layer
{
 CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
 // 讓CALayer的時間停止走動
 layer.speed = 0.0;
 // 讓CALayer的時間停留在pausedTime這個時刻
 layer.timeOffset = pausedTime;
}
 
#pragma mark 恢復CALayer的動畫
-(void)resumeLayer:(CALayer*)layer
{
 CFTimeInterval pausedTime = layer.timeOffset;
 // 1. 讓CALayer的時間繼續行走
 layer.speed = 1.0;
 // 2. 取消上次記錄的停留時刻
 layer.timeOffset = 0.0;
 // 3. 取消上次設置的時間
 layer.beginTime = 0.0;
 
 // 4. 計算暫停的時間(這裏也可以用CACurrentMediaTime()-pausedTime)
 CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
 // 5. 設置相對於父座標系的開始時間(往後退timeSincePause)
 layer.beginTime = timeSincePause;
}

4.CAPropertyAnimation

4.1.CAPropertyAnimation 是 CAAnimation 的子類,也是個抽象類,要想創建動畫對象,應該使用它的兩個子類: CABasicAnimation, CAKeyframeAnimation 。

4.2.屬性說明:


keyPath 通過指定 CALayer 的一個屬性名稱爲 keyPath ( NSString 類型),並且對 CALayer 的這個屬性的值進行修改,達到相應的動畫效果。比如,指定 @”position” 爲 keyPath,就修改 CALayer 的 position 屬性的值,以達到平移的動畫效果。

5.CABasicAnimation

5.1.基本 CABasicAnimation,是 CAPropertyAnimation 的子類。

5.2.屬性說明:


fromValue keyPath 相應屬性的初始值
toValue keyPath 相應屬性的結束值

5.3.動畫過程說明:

5.3.1.隨着動畫的進行,在長度爲 duration 的持續時間內,keyPath 相應屬性的值從 fromValue 漸漸地變爲 toValue 。

5.3.2.keyPath 內容是 CALayer 的可動畫 Animatable 屬性。

5.3.3.如果 fillMode = kCAFillModeForwards 同時 removedOnComletion = NO ,那麼在動畫執行完畢後,圖層會保持顯示動畫執行後的狀態。但在實質上,圖層的屬性值還是動畫執行前的初始值,並沒有真正被改變 。

5.3.4.如果只是實現簡單屬性變化的動畫效果,可以使用 UIView 的 block 動畫替代基本動畫。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/***平移***/
// 1. 實例化動畫
// 如果沒有指定圖層的錨點(定位點)postion對應UIView的中心點
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
// 2. 設置動畫屬性
// 1) fromValue(myView的當前座標) & toValue
[anim setToValue:[NSValue valueWithCGPoint:point]];
// 2) 動畫的時長
[anim setDuration:1.0f];
// 3) 設置代理
[anim setDelegate:self];
// 4) 讓動畫停留在目標位置
/*
 *提示:通過設置動畫在完成後不刪除,以及向前填充,可以做到平移動畫結束後,
 *UIView看起來停留在目標位置,但是其本身的frame並不會發生變化
 */
[anim setRemovedOnCompletion:NO];
// forwards是逐漸逼近目標點
[anim setFillMode:kCAFillModeForwards];
// 5) 要修正座標點的實際位置可以利用setValue方法
[anim setValue:[NSValue valueWithCGPoint:point] forKey:@"targetPoint"];
[anim setValue:@"translationTo" forKey:@"animationType"];
// 3. 將動畫添加到圖層
// 將動畫添加到圖層之後,系統會按照定義好的屬性開始動畫,通常程序員不在與動畫進行交互
[self.myView.layer addAnimation:anim forKey:nil];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/***代理方法***/
//動畫開始(極少用)
- (void)animationDidStart:(CAAnimation *)anim
{
    NSLog(@"開始動畫");
}
//動畫結束(通常在動畫結束後,做動畫的後續處理)
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    NSString *type = [anim valueForKey:@"animationType"];
    if ([type isEqualToString:@"translationTo"]) {
        // 1. 通過鍵值取出需要移動到的目標點
        CGPoint point = [[anim valueForKey:@"targetPoint"]CGPointValue];
        NSLog(@"目標點: %@", NSStringFromCGPoint(point));
        // 2. 設置myView的座標點
        [self.myView setCenter:point];
    }
 NSLog(@"結束動畫,myView: %@", NSStringFromCGRect(self.myView.frame));
}
1
2
3
4
5
6
/***block 動畫***/
[UIView animateWithDuration:1.0f animations:^{
    [self.myView setCenter:location];
} completion:^(BOOL finished) {
    NSLog(@"%@", NSStringFromCGRect(self.myView.frame));
}];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/***旋轉動畫***/
// 1. 實例化基本動畫
// 默認按照z軸旋轉
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
[self.myView.layer setAnchorPoint:CGPointMake(0, 0)];
// 2. 設置動畫屬性
// 不停的旋轉
// 1) 旋轉一週
[anim setToValue:@(2 * M_PI)];
// 2) 不停的旋轉 - 動畫循環播放
// HUGE_VALF 是一個非常大得浮點數,指定此數值可以認爲動畫無限循環,這裏不要使用 MAXFLOAT
[anim setRepeatCount:HUGE_VALF];
[anim setDuration:0.5f];
// 3) 動畫完成時刪除
// 對於循環播放的動畫效果,一定要將 removedOnCompletion 設置爲 NO,否則無法恢復動畫
[anim setRemovedOnCompletion:NO];
// 3. 添加動畫
// key 可以隨便指定,用於判斷圖層中是否存在該動畫
[self.myView.layer addAnimation:anim forKey:@"rotationAnim"];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/***縮放動畫***/
// 1. 實例化基本動畫
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
// 2. 設置動畫屬性
// fromValue & toValue
[anim setFromValue:@(1.0)];
// 從當前大小縮小到一半,然後恢復初始大小
[anim setToValue:@(0.5)];
// 自動翻轉動畫
[anim setAutoreverses:YES];
// 動畫時長
[anim setDuration:0.5f];
// 3. 將動畫添加到圖層
[self.myView.layer addAnimation:anim forKey:nil];

6.CAKeyframeAnimation

6.1.CAKeyframeAnimation ,也是 CAPropertyAnimation 的子類。

6.2.與 CABasicAnimation 的區別是:

6.2.1.CABasicAnimation 只能從一個數值( fromValue )變到另一個數值( toValue ),而 CAKeyframeAnimation 會使用一個 NSArray 保存這些數值 。

6.2.2.CABasicAnimation 可看做是隻有2個關鍵幀的 CAKeyframeAnimation 。

6.3.常用屬性:


values 上述的NSArray對象。裏面的元素稱爲”關鍵幀” ( keyframe )。動畫對象會在指定的時間( duration )內,依次顯示 values 數組中的每一個關鍵幀。
path 可以設置一個 CGPathRef、 CGMutablePathRef ,讓圖層按照路徑軌跡移動。path 只對 CALayer 的 anchorPoint 和position 起作用。如果設置了 path,那麼 values 將被忽略。
keyTimes 可以爲對應的關鍵幀指定對應的時間點,其取值範圍爲0到1.0,keyTimes 中的每一個時間值都對應values中的每一幀。如果沒有設置 keyTimes ,各個關鍵幀的時間是平分的。
1
2
3
4
5
6
7
8
9
10
11
/***晃動動畫***/
//實例化關鍵幀動畫
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
[anim setDuration:0.5f];
//晃動角度
CGFloat angel = M_PI_4 / 12.0;
[anim setValues:@[@(angel), @(-angel), @(angel)]];
//設置循環晃動
[anim setRepeatCount:HUGE_VALF];
//將動畫添加到圖層
[self.layer addAnimation:anim forKey:nil];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***離散點平移動畫***/
// 1. 實例化關鍵幀動畫
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 2. 設置關鍵幀動畫屬性
NSValue *p1 = [NSValue valueWithCGPoint:self.center];
NSValue *p2 = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
NSValue *p3 = [NSValue valueWithCGPoint:point];
[anim setValues:@[p1, p2, p3]];
[anim setDuration:1.0f];
//設置鍵值記錄目標位置,以便動畫結束後,修正位置
[anim setValue:@"translationTo" forKey:@"animationType"];
[anim setValue:p3 forKey:@"targetPoint"];
//設置代理
[anim setDelegate:self];
// 3. 將動畫添加到圖層
[self.layer addAnimation:anim forKey:nil];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/***路徑平移動畫***/
// 1. 實例化關鍵幀動畫
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[anim setDuration:duration];
// 2. 按照矩形移動,需要使用到路徑
// 1) 創建路徑
CGMutablePathRef path = CGPathCreateMutable();
// 2) 設置路徑內容
// 起點,寬、高
CGFloat w = to.x - self.center.x;
CGFloat h = to.y - self.center.y;
CGRect rect = CGRectMake(self.center.x, self.center.y, w, h);
CGPathAddRect(path, nil, rect);
// 3) 將路徑添加到動畫
[anim setPath:path];
// 4) 釋放路徑
CGPathRelease(path);
// 3. 將動畫添加到圖層
[self.layer addAnimation:anim forKey:nil];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/***貝塞爾曲線(一個控制點)動畫***/
// 1. 實例化關鍵幀動畫
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[anim setDuration:duration];
// 2. 設置路徑
// 中間的控制點使用屏幕上得隨機點
CGPoint cp = [self randomPoint];
CGMutablePathRef path = CGPathCreateMutable();
// 設置起始點
CGPathMoveToPoint(path, NULL, self.center.x, self.center.y);
// 添加帶一個控制點的貝塞爾曲線
CGPathAddQuadCurveToPoint(path, NULL, cp.x, cp.y, to.x, to.y);
[anim setPath:path];
CGPathRelease(path);
// 設置鍵值記錄目標位置,以便動畫結束後,修正位置
[anim setValue:@"translationTo" forKey:@"animationType"];
[anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
[anim setDelegate:self];
// 3. 將動畫添加到圖層
[self.layer addAnimation:anim forKey:nil];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***貝塞爾曲線(兩個控制點)動畫***/
// 1. 實例化關鍵幀動畫
CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 2. 設置路徑
[anim setDuration:duration];
// 中間的控制點使用屏幕上得隨機點
CGPoint cp1 = [self randomPoint];
CGPoint cp2 = [self randomPoint];
CGMutablePathRef path = CGPathCreateMutable();
// 設置起始點
CGPathMoveToPoint(path, NULL, self.center.x, self.center.y);
// 添加帶一個控制點的貝塞爾曲線
CGPathAddCurveToPoint(path, NULL, cp1.x, cp1.y, cp2.x, cp2.y, to.x, to.y);
[anim setPath:path];
CGPathRelease(path);
// 設置鍵值記錄目標位置,以便動畫結束後,修正位置
[anim setValue:@"translationTo" forKey:@"animationType"];
[anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
[anim setDelegate:self];
// 3. 將動畫添加到圖層
[self.layer addAnimation:anim forKey:nil];
1
2
3
4
5
6
7
8
9
10
/***動畫代理方法***/
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    // 取出動畫類型
    NSString *type = [anim valueForKey:@"animationType"];
    if ([type isEqualToString:@"translationTo"]) {
        // 取出目標點,並設置self.center
        self.center = [[anim valueForKey:@"targetPoint"]CGPointValue];
    }
}

6.4.CAKeyframeAnimation 計算模式屬性 (calculationMode)

6.4.1.所謂計算模式:其主要針對的是每一幀的內容爲一個座標點的情況,也就是對 anchorPoint 和 position 進行的動畫。

6.4.2.當在平面座標系中有多個離散的點的時候,可以是離散的,也可以直線相連後進行插值計算,也可以使用圓滑的曲線將他們相連後進行插值計算。

6.4.3.calculationMode目前提供如下幾種模式:


kCAAnimationLinear 默認值,表示當關鍵幀爲座標點的時候,關鍵幀之間直接直線相連進行插值計算
kCAAnimationDiscrete 離散的,不進行插值計算,所有關鍵幀直接逐個進行顯示
kCAAnimationPaced 使得動畫均勻進行,而不是按 keyTimes 設置的或者按關鍵幀平分時間,此時 keyTimes 和 timingFunctions 無效
kCAAnimationCubic 對關鍵幀爲座標點的關鍵幀進行圓滑曲線相連後插值計算,這裏的主要目的是使得運行的軌跡變得圓滑
kCAAnimationCubicPaced 在 kCAAnimationCubic 的基礎上使得動畫運行變得均勻,就是系統時間內運動的距離相同,此時 keyTimes 以及 timingFunctions 也是無效的。

6.4.4.此屬性研究的優先級不高,只有再做複雜動畫,同時動畫效果不理想的時候,才需要考慮使用這一屬性。

7.CAAnimationGroup

7.1.CAAnimationGroup,是CAAnimation的子類,可以保存一組動畫對象,將CAAnimationGroup對象加入層後,組中所有動畫對象可以同時併發運行。

7.2.屬性說明:


animations 用來保存一組動畫對象的 NSArray

7.3.默認情況下,一組動畫對象是同時運行的,也可以通過設置動畫對象的 beginTime 屬性來更改動畫的開始時間。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/***動畫組***/
// 1. 實例化動畫組
CAAnimationGroup *group = [[CAAnimationGroup alloc]init];
CFTimeInterval duration = 2.0;
// 2. 定義動畫組中的動畫
CAKeyframeAnimation *move = [AnimationView moveWithDuration:duration from:self.myView.center to:location controlPointCount:4];
CABasicAnimation *rotation = [AnimationView rotationWithDuration:duration from:0.0 to:2 * M_PI];
CABasicAnimation *scale = [AnimationView scaleWithDuration:duration from:2.0 to:0.5];
CABasicAnimation *opacity = [AnimationView opacityWithDuration:duration from:0.1 to:1.0];
// 3. 將定義的動畫添加到動畫組
[group setAnimations:@[move, rotation, scale, opacity]];
// 定義動畫組執行的時間長度
[group setDuration:duration];
// 5) 設置鍵值記錄目標位置,以便動畫結束後,修正位置
// 並不是所有的動畫方法都需要設置目標點
[group setValue:@"translationTo" forKey:@"animationType"];
[group setValue:[NSValue valueWithCGPoint:location] forKey:@"targetPoint"];
[group setDelegate:self];
// 4. 將動畫組添加到視圖的圖層
[self.myView.layer addAnimation:group forKey:nil];
1
2
3
4
5
6
7
8
9
10
/***動畫代理方法***/
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    // 取出動畫類型
    NSString *type = [anim valueForKey:@"animationType"];
    if ([type isEqualToString:@"translationTo"]) {
        // 取出目標點,並設置self.center
        self.center = [[anim valueForKey:@"targetPoint"]CGPointValue];
    }
}

8.CATransition

8.1.CATransition 是 CAAnimation 的子類,用於做轉場動畫,能夠爲層提供移出屏幕和移入屏幕的動畫效果。 iOS 比 Mac OS X 的轉場動畫效果少一點。

8.2.UINavigationController 就是通過 CATransition 實現了將控制器的視圖推入屏幕的動畫效果。

8.3.動畫屬性:


type 動畫過渡類型
subtype 動畫過渡方向
startProgress 動畫起點(在整體動畫的百分比)
endProgress 動畫終點(在整體動畫的百分比)

8.4.轉場動畫過渡效果:


 類型字符串  效果說明 關鍵字 方向
fade 交叉淡化過渡  YES  
push 新視圖把舊視圖推出去  YES  
moveIn 新視圖移到舊視圖上面  YES  
reveal 將舊視圖移開,顯示下面的新視圖  YES  
cube 立方體翻滾效果    
oglFlip 上下左右翻轉效果    
suckEffect 收縮效果,如一塊布被抽走    NO
rippleEffect 水滴效果    NO
pageCurl 向上翻頁效果    
pageUnCurl 向下翻頁效果    
cameraIrisHollowOpen 相機鏡頭打開效果    NO
cameraIrisHollowClose 相機鏡頭關閉效果    NO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1. 實例化轉場動畫 注意不要和CATransaction(動畫事務)搞混
CATransition *transition = [[CATransition alloc]init];
// 設置類型 type
[transition setType:@"moveIn"];
// 根據輕掃方向設置子類型 subType
// 2. 判斷輕掃的方向
UIImageView *imageView = (UIImageView *)recognizer.view;
if (UISwipeGestureRecognizerDirectionLeft == recognizer.direction) {
    NSLog(@"向左");
    [transition setSubtype:kCATransitionFromRight];
    imageView.tag = (imageView.tag + 1) % self.imageList.count;
} else {
    NSLog(@"向右");
    [transition setSubtype:kCATransitionFromLeft];
    // 針對負數去模,需要注意修正索引
    imageView.tag = (imageView.tag - 1 + self.imageList.count) % self.imageList.count;
}
[transition setDuration:0.5f];
[imageView setImage:self.imageList[imageView.tag]];
// 3. 動畫添加到圖層
[recognizer.view.layer addAnimation:transition forKey:nil];

8.5.使用UIView動畫函數實現轉場動畫(單視圖):

1
2
3
4
5
6
7
8
/*
 * duration:動畫的持續時間
 * view:需要進行轉場動畫的視圖
 * options:轉場動畫的類型
 * animations:將改變視圖屬性的代碼放在這個block中
 * completion:動畫結束後,會自動調用這個block
 */
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
1
2
3
4
5
6
7
8
/***單視圖(翻轉轉場動畫)***/
[UIView transitionWithView:self.imageView duration:1.0f options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
    // 在此設置視圖反轉之後顯示的內容
    self.imageView.tag = (self.imageView.tag + 1) % self.imageList.count;
    [self.imageView setImage:self.imageList[self.imageView.tag]];
} completion:^(BOOL finished) {
    NSLog(@"翻轉完成");
}];

8.6.使用 UIView 動畫函數實現轉場動畫(雙視圖):

1
2
3
4
5
6
7
/*
 * duration:動畫的持續時間
 * options:轉場動畫的類型
 * animations:將改變視圖屬性的代碼放在這個block中
 * completion:動畫結束後,會自動調用這個block
 */
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/***雙視圖***/
// 在雙視圖轉場時,我們可以根據是否有父視圖,來判斷誰進誰出
UIView *fromView = nil;
UIView *toView = nil;
if (self.subView1.superview == nil) {
    // 說明subView1要轉入
    toView = self.subView1;
    fromView = self.subView2;
} else {
    // 說明subView2要轉入
    toView = self.subView2;
    fromView = self.subView1;
}
[UIView transitionFromView:fromView toView:toView duration:1.0f options:UIViewAnimationOptionTransitionFlipFromTop completion:^(BOOL finished) {
    NSLog(@"轉場完成");
    // 每次轉場後,會調整參與轉場視圖的父視圖,因此,參與轉場視圖的屬性,需要是強引用
    // 轉場之後,入場的視圖會有兩個強引用,一個是視圖控制器,另一個是視圖
    NSLog(@"subView1's superView: %@", self.subView1.superview);
    NSLog(@"subView2's superView: %@", self.subView2.superview);
}];

8.6.1.使用雙視圖轉場動畫時,需要掌握視圖的 superView 屬性的變化。

8.6.2.方法調用完畢後,相當於執行了下面兩句代碼:

1
2
3
4
// 添加toView到父視圖
[fromView.superview addSubview:toView];
// 把fromView從父視圖中移除
[fromView.superview removeFromSuperview];

8.7.轉場動畫存在的問題是動畫過程中無法交互,如果要在切換時實現交互效果需要使用 UIScrollView + UIPageControl 。

9.UIActivityIndicatorView

9.1.UIActivityIndicatorView 是一個旋轉進度輪,可以用來告知用戶有一個操作正在進行中,一般用initWithActivityIndicatorStyle 初始化。

9.2.相關方法:


- (void)startAnimating;  開始動畫
- (void)stopAnimating;  停止動畫
- (BOOL)isAnimating;  是否正在運行動畫

9.3.屬性數值:


UIActivityIndicatorViewStyleWhiteLarge 大型白色指示器
UIActivityIndicatorViewStyleWhite 標準尺寸白色指示器
UIActivityIndicatorViewStyleGray 灰色指示器,用於白色背景

9.3.常用第三方框架 SVProgressHUB

9.3.1.常用顯示方法:showWithStatus ; showWithStatus:maskType:

9.3.2.關閉方法:dismiss

9.3.3.SVProgressHUB 對 UIActivityIndicatorView 進行了封裝,增加了文字、圖像以及容器視圖等屬性,通過類方法調用,使用簡單。

9.3.4.使用 SVProgressHUDMaskTypeGradient 等屬性顯示提示信息時,可以使用 NSTimer 模擬等待後臺響應效果。

10.UIImageView 的序列幀動畫

10.1.UIImageView可以讓一系列的圖片在特定的時間內按順序顯示。

10.2.屬性說明:


animationImages 要顯示的一組圖片序列
animationDuration 完整地顯示所有圖片所需的時間
animationRepeatCount 動畫的執行次數(默認爲0,代表無限循環)

10.3.相關方法:


- (void)startAnimating;  開始動畫
- (void)stopAnimating;  停止動畫
- (BOOL)isAnimating;  是否正在運行動畫

11.CADisplayLink

11.1.CADisplayLink 是一種以屏幕刷新頻率觸發的時鐘機制,每秒鐘執行大約60次左右。

11.2.CADisplayLink 是一個計時器,可以使繪圖代碼與視圖的刷新頻率保持同步,而 NSTimer 無法確保計時器實際被觸發的準確時間。

11.3.使用方法:

11.3.1.定義 CADisplayLink 並制定觸發調用方法

11.3.2.將顯示鏈接添加到主運行循環隊列

1
2
3
4
5
// 實例化遊戲時鐘
// 1. 實例化遊戲時鐘,並添加監聽方法
self.gameTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step)];
// 2. 添加到主運行循環,否則監聽方法不會被觸發
[self.gameTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章