iOS Core Animation 核心動畫(上)

一、簡介

Core Animation,中文翻譯為核心動畫,它是一組非常強大的動畫處理API,使用它能做出非常炫麗的動畫效果,而且往往是事半功倍。也就是說,使用少量的代碼就可以實現非常強大的功能。

Core Animation是跨平臺的,可以用在Mac OS X和iOS平臺。

Core Animation的動畫執行過程都是在后臺操作的,不會阻塞主線程。不阻塞主線程,可以理解為在執行動畫的時候還能點擊(按鈕)。

要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。

Core Animation的使用步驟

1.使用它需要先添加QuartzCore.framework框架和引入主頭文件(iOS7不需要)

2.初始化一個CAAnimation對象,并設置一些動畫相關屬性

3.通過調用CALayer的addAnimation:forKey:方法增加CAAnimation對象到CALayer中,這樣就能開始執行動畫了

4.通過調用CALayer的removeAnimationForKey:方法可以停止CALayer中的動畫

屬性及說明

CAAnimation是所有動畫類的父類,但是它不能直接使用,應該使用它的子類。

(1)能用的動畫類只有4個子類:CABasicAnimation(基礎動畫)、CAKeyframeAnimation(關鍵幀動畫)、CATransition(轉場動畫)、CAAnimationGroup(組動畫)

(2)CAMediaTiming是一個協議(protocol)。

CAPropertyAnimation是CAAnimation的子類,但是不能直接使用,要想創建動畫對象,應該使用它的兩個子類:CABasicAnimation(基礎動畫)和CAKeyframeAnimation(關鍵幀動畫)

屬性:((**)代表來自CAMediaTiming協議的屬性)

duration:(**)動畫的持續時間

repeatCount:(**)動畫的重復次數

repeatDuration:(**)動畫的重復時間

removedOnCompletion:默認為YES,代表動畫執行完畢后就從圖層上移除,圖形會恢復到動畫執行前的狀態。如果想讓圖層保持顯示動畫執行后的狀態,那就設置為NO,不過還要設置fillMode為kCAFillModeForwards

fillMode:(**)決定當前對象在非active時間段的行為.比如動畫開始之前,動畫結束之后

beginTime:(**)可以用來設置動畫延遲執行時間,若想延遲2s,就設置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當前時間

timingFunction:速度控制函數,控制動畫運行的節奏

delegate:動畫代理

二、基礎動畫 CABasicAnimation

CAPropertyAnimation的子類

屬性解析:

fromValue:keyPath相應屬性的初始值

toValue:keyPath相應屬性的結束值

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

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

比如,CALayer的position初始值為(0,0),CABasicAnimation的fromValue為(10,10),toValue為(100,100),雖然動畫執行完畢后圖層保持在(100,100)這個位置,實質上圖層的position還是為(0,0)

1、平移動畫

創建layer

CALayer *myLayer=[CALayer layer];

//設置layer的屬性

myLayer.bounds=CGRectMake(0, 0, 50, 80);

myLayer.backgroundColor=[UIColor yellowColor].CGColor;

myLayer.position=CGPointMake(50, 50);

myLayer.anchorPoint=CGPointMake(0, 0);

myLayer.cornerRadius=20;

//添加layer

[self.view.layer addSublayer:myLayer];

//設置動畫(基礎動畫)

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

//1.創建核心動畫

//? ? CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]

CABasicAnimation *anima=[CABasicAnimation animation];

//1.1告訴系統要執行什么樣的動畫? 設置的keyPath是@"position",說明要修改的是CALayer的position屬性,也就是會執行平移動畫

anima.keyPath=@"position";

//設置通過動畫,將layer從哪兒移動到哪兒? 這里的屬性接收的時id類型的參數,因此并不能直接使用CGPoint這種結構體類型,而是要先包裝成NSValue對象后再使用。

//byValue和toValue的區別,byValue--是在當前的位置上增加多少,toValue--是移動到指定的位置。

anima.fromValue=[NSValue valueWithCGPoint:CGPointMake(0, 0)];

anima.toValue=[NSValue valueWithCGPoint:CGPointMake(200, 300)];

//1.2設置動畫執行完畢之后不刪除動畫

anima.removedOnCompletion=NO;

//1.3設置保存動畫的最新狀態

anima.fillMode=kCAFillModeForwards;

//2.添加核心動畫到layer

[myLayer addAnimation:anima forKey:nil];

}


效果

設置代理:設置動畫的代理,可以監聽動畫的執行過程,這里設置控制器為代理。

-(void)animationDidStart:(CAAnimation *)anim{

NSLog(@"開始執行動畫");

}

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{

//動畫執行完畢,打印執行完畢后的position值

NSString *str=NSStringFromCGPoint(self.myLayer.position);

NSLog(@"執行后:%@",str);//打印position的屬性值,驗證圖層的屬性值還是動畫執行前的初始值{50,50},并沒有真正被改變為{200,300}。

}

2、縮放動畫

//創建layer

CALayer *myLayer=[CALayer layer];

myLayer.bounds=CGRectMake(0, 0, 150, 60);

myLayer.backgroundColor=[UIColor yellowColor].CGColor;

myLayer.position=CGPointMake(50, 50);

myLayer.anchorPoint=CGPointMake(0, 0);

myLayer.cornerRadius=40;

[self.view.layer addSublayer:myLayer];

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

//1.創建動畫

CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"bounds"];

//1.1設置動畫執行時間

anima.duration=2.0;

//1.2設置動畫執行完畢后不刪除動畫

anima.removedOnCompletion=NO;

//1.3設置保存動畫的最新狀態

anima.fillMode=kCAFillModeForwards;

//1.4修改屬性,執行動畫

anima.toValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];

//2.添加動畫到layer

[myLayer addAnimation:anima forKey:nil];

}

效果

3、旋轉動畫

//創建layer(同縮放)

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

//1.創建動畫

CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"transform"];

//1.1設置動畫執行時間

anima.duration=2.0;

//1.2修改屬性,執行動畫? 如果要讓圖形以2D的方式旋轉,只需要把CATransform3DMakeRotation在z方向上的值改為1即可。

anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];

//1.3設置動畫執行完畢后不刪除動畫

anima.removedOnCompletion=NO;

//1.4設置保存動畫的最新狀態

anima.fillMode=kCAFillModeForwards;

//2.添加動畫到layer

[self.myLayer addAnimation:anima forKey:nil];

}

anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];

效果

4、補充

4.1、可以通過transform(KVC)的方式來進行設置

4.2、fillMode的作用就是決定當前對象過了非active時間段的行為. 比如動畫開始之前,動畫結束之后。如果是一個動畫CAAnimation,則需要將其removedOnCompletion設置為NO,要不然fillMode不起作用.

各個fillMode的意義

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

kCAFillModeForwards - 當動畫結束后,layer會一直保持著動畫最后的狀態

kCAFillModeBackwards - 這個和kCAFillModeForwards是相對的,就是在動畫開始前,你只要將動畫加入了一個layer,layer便立即進入動畫的初始狀態并等待動畫開始.你可以這樣設定測試代碼,將一個動畫加入一個layer的時候延遲5秒執行.然后就會發現在動畫沒有開始的時候,只要動畫被加入了layer,layer便處于動畫初始狀態

kCAFillModeBoth - 理解了上面兩個,這個就很好理解了,這個其實就是上面兩個的合成.動畫加入后開始之前,layer便處于動畫初始狀態,動畫結束后layer保持動畫最后的狀態.

三、關鍵幀動畫 CAKeyframeAnimation

1、簡介

CAKeyframeAnimation是CApropertyAnimation的子類,跟CABasicAnimation的區別是:CABasicAnimation只能從一個數值(fromValue)變到另一個數值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數值

屬性解析:

values:就是上述的NSArray對象。里面的元素稱為”關鍵幀”(keyframe)。動畫對象會在指定的時間(duration)內,依次顯示values數組中的每一個關鍵幀

path:可以設置一個CGPathRef\CGMutablePathRef,讓層跟著路徑移動。path只對CALayer的anchorPoint和position起作用。如果你設置了path,那么values將被忽略

keyTimes:可以為對應的關鍵幀指定對應的時間點,其取值范圍為0到1.0,keyTimes中的每一個時間值都對應values中的每一幀.當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的

說明:CABasicAnimation可看做是最多只有2個關鍵幀的CAKeyframeAnimation

2、平移

@property (nonatomic, strong) UIView *customView;

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

//1.創建核心動畫

CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];

keyAnima.keyPath = @"position";//平移

//1.1告訴系統要執行什么動畫

keyAnima.values = @[[NSValue valueWithCGPoint:CGPointMake(100, 100)],

[NSValue valueWithCGPoint:CGPointMake(200, 100)],

[NSValue valueWithCGPoint:CGPointMake(200, 200)],

[NSValue valueWithCGPoint:CGPointMake(100, 200)],

[NSValue valueWithCGPoint:CGPointMake(100, 100)]];

//1.2設置動畫執行完畢后,不刪除動畫? 默認為YES,代表動畫執行完畢后就從圖層上移除,圖形會恢復到動畫執行前的狀態。如果想讓圖層保持顯示動畫執行后的狀態,那就設置為NO,不過還要設置fillMode為kCAFillModeForwards

keyAnima.removedOnCompletion = NO;

//1.3設置保存動畫的最新狀態

keyAnima.fillMode = kCAFillModeForwards;

//1.4設置動畫執行的時間

keyAnima.duration = 4.0;

//1.5速度控制函數,控制動畫運行的節奏

keyAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

//設置代理,開始—結束

keyAnima.delegate = self;

//2.添加核心動畫

[self.customView.layer addAnimation:keyAnima forKey:nil];

//beginTime:可以用來設置動畫延遲執行時間,若想延遲2s,就設置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當前時間

}

-(void)animationDidStart:(CAAnimation *)anim{

NSLog(@"開始動畫"); }

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
NSLog(@"結束動畫"); }

1.5----

設置動畫的節奏

3、使用path,讓layer在指定的路徑上移動(畫圓)

//1.創建核心動畫

CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];

keyAnima.keyPath=@"position";//平移

//1.1告訴系統要執行什么動畫

//創建一條路徑

CGMutablePathRef path = CGPathCreateMutable();

//設置一個圓的路徑

CGPathAddEllipseInRect(path, NULL, CGRectMake(150, 100, 100, 100));

keyAnima.path = path; //可以通過path屬性,讓layer在指定的軌跡上運動。

//有create就一定要有release

CGPathRelease(path);

//1.2...1.5 同上

//2.添加核心動畫

[self.customView.layer addAnimation:keyAnima forKey:@"key"];

//3 動畫停止

- (void)stopOnClick:(UIButton *)button {

//停止self.customView.layer上名稱標示為key的動畫

[self.customView.layer removeAnimationForKey:@"key"];

//[self.customView.layer removeAllAnimations];//移除全部動畫

}

4、抖動(旋轉)

#define angle2Radian(angle)? ((angle)/180.0*M_PI)

//1.創建核心動畫

CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];

keyAnima.keyPath = @"transform.rotation";//旋轉

//設置動畫時間

keyAnima.duration = 0.1;

//設置圖標抖動弧度

//把度數轉換為弧度? 度數/180*M_PI

keyAnima.values = @[@(-angle2Radian(4)), @(angle2Radian(4)), @(-angle2Radian(4))];//向左向右偏轉一個弧度(4),產生抖動的視覺效果

//設置動畫的重復次數(設置為最大值)

keyAnima.repeatCount = MAXFLOAT;

keyAnima.fillMode = kCAFillModeForwards;

keyAnima.removedOnCompletion = NO;

//2.添加動畫

[self.iconView.layer addAnimation:keyAnima forKey:nil];

四、轉場動畫 CATransition

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

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

屬性解析:

type:動畫過渡類型

subtype:動畫過渡方向

startProgress:動畫起點(在整體動畫的百分比)

endProgress:動畫終點(在整體動畫的百分比)

1、界面

界面搭建 & 實例效果圖

2、代碼

@property(nonatomic,assign)intindex;

@property (nonatomic, strong) UIImageView *iconView;

- (IBAction)preOnClick:(UIButton *)sender;

- (IBAction)nextOnClick:(UIButton *)sender;

- (void)viewDidLoad{

[super viewDidLoad];

self.index=1;

}

//上一張

- (IBAction)preOnClick:(UIButton *)sender {

self.index--;

if (self.index<1) {

self.index=7;

}

self.iconView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];

//創建核心動畫

CATransition *ca=[CATransition animation];

//告訴要執行什么動畫

//設置過度效果

ca.type=@"cube";

//設置動畫的過度方向(向左)

ca.subtype=kCATransitionFromLeft;

//設置動畫的時間

ca.duration=2.0;

//添加動畫

[self.iconView.layer addAnimation:ca forKey:nil];? }

//下一張

- (IBAction)nextOnClick:(UIButton *)sender {

self.index++;

if (self.index>7) {

self.index=1;

}

self.iconView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];

//1.創建核心動畫

CATransition *ca=[CATransition animation];

//1.1告訴要執行什么動畫

//1.2設置過度效果

ca.type=@"cube";

//1.3設置動畫的過度方向(向右)

ca.subtype=kCATransitionFromRight;

//1.4設置動畫的時間

ca.duration=2.0;

//1.5設置動畫的起點

ca.startProgress=0.5;

//1.6設置動畫的終點

//? ? ca.endProgress=0.5;

//2.添加動畫

[self.iconView.layer addAnimation:ca forKey:nil]; }

五、組動畫 CAAnimationGroup

1、簡介

CAAnimation的子類,可以保存一組動畫對象,將CAAnimationGroup對象加入層后,組中所有動畫對象可以同時并發運行

屬性解析:

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

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

2、代碼

// 平移動畫

CABasicAnimation *a1 = [CABasicAnimation animation];

a1.keyPath = @"transform.translation.y";

a1.toValue = @(100);

// 縮放動畫

CABasicAnimation *a2 = [CABasicAnimation animation];

a2.keyPath = @"transform.scale";

a2.toValue = @(0.0);

// 旋轉動畫

CABasicAnimation *a3 = [CABasicAnimation animation];

a3.keyPath = @"transform.rotation";

a3.toValue = @(M_PI_2);

// 組動畫

CAAnimationGroup *groupAnima = [CAAnimationGroup animation];

groupAnima.animations = @[a1, a2, a3];

//設置組動畫的時間

groupAnima.duration = 2;

groupAnima.fillMode = kCAFillModeForwards;

groupAnima.removedOnCompletion = NO;

[self.iconView.layer addAnimation:groupAnima forKey:nil];

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容