我們看到很多App帶有絢麗狂拽的特效,別出心裁的控件設計,很大程度上提高了用戶體驗,在增加了實用性的同時,也賦予了app無限的生命力。這些華麗的效果很多都是基於iOS的核心動畫原理實現的,本文介紹一些iOS開發中最基本的動畫效果實現,掌握了基本屬性,才可以繪制出更華麗的效果。
一、概念擴充
1、核心動畫:
Core Animation,它是一組非常強大的動畫處理API,使用它能做出非常炫麗的動畫效果,而且往往是事半功倍。 Core Animation可以用在Mac OS X和iOS平台。在iOS平台中,動畫效果會略少一些。另外,iOS開發中實現動畫的方式也不只是核心動畫一種,後面會介紹UIView的幾種動畫。
2、執行和創建動畫過程:
(1)Core Animation的動畫執行過程都是在後台操作的,不會阻塞主線程。要注意的是,Core Animation是直接作用在CALayer上的,並非UIView。所以,CALayer是核心動畫的基礎。
(2)關於框架:iOS7以後,不再需要導入QuartzCore.framework框架和主頭文件<QuartzCore/QuartzCore.h>
(3)基本的創建動畫流程
3、動畫類型:後面做詳細的使用介紹
4、本質與繼承關系:
(1)本質:在後台移動圖層中的內容, 執行完畢後圖層本身的位置並沒有發生變化。
(2)所有的動畫都繼承自CAAnimation
二、CAAnimation
1、定義:
所有動畫對象的父類,負責控制動畫的持續時間和速度,是個抽象類,不能直接使用,應該使用它具體的子類。
2、 屬性解析:(很多屬性都是來自CAMediaTiming協議)
3、隱式代理:delegate
(1) CAAnimation有一個id類型的delegate屬性,但是此屬性沒有遵守任何協議,本身也沒有任何代理協議。
(2) 實現代理方法:注意,這裡的兩個方法,是在NSObject擴展中聲明的,所以是本身就是NSObject的方法,每一個類都能實現該方法。o(╯□╰)o。。
(3)給CAAnimation的delegate賦值(說明誰來代理)、重寫代理方法,就可以實現“隱式”代理。
三、CAPropertyAnimation
1、定義:
是CAAnimation的子類,也是個抽象類,要想創建動畫對象,應該使用它的兩個子類:CABasicAnimation和CAKeyframeAnimation。
2、屬性解析:
(1)圖1:position屬性———CGPoint類型

(2)圖2:frame和bounds屬性 ———CGRect類型

(3)圖3:transform屬性 ————CATransform3D 類型

四、CABasicAnimation 基本動畫
1、定義:
基本動畫,CAPropertyAnimation的子類。通過設置keyPath,兩個值之間的變化實現動畫。
2、屬性解析:
隨著動畫的進行,在長度為duration的持續時間內,keyPath相應屬性的值從fromValue漸漸地變為toValue,如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那麼在動畫執行完畢後,圖層會保持顯示動畫執行後的狀態。但在實質上,圖層的屬性值還是動畫執行前的初始值,並沒有真正被改變。比如,CALayer的position初始值為(0,0),CABasicAnimation的fromValue為(10,10),toValue為(100,100),雖然動畫執行完畢後圖層保持在(100,100)這個位置,實質上圖層的position還是為(0,0)
3、代碼案例:
給出一個基本動畫和關鍵幀動畫的基本配置案例
效果:

#pragma mark - 基本動畫:按路徑移動(默認返回原位)
- (IBAction)moveAtPathBack:(UIButton *)sender {
//設置keyPath 為:transform.translation.x
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
//起始值
animation.fromValue= @(150);
//到達值
animation.toValue = @(-150);
animation.duration=1;
//要添加到layer
[self.button.layer addAnimation:animation forKey:nil];
}
#pragma mark - 基本動畫:按路徑移動(不返回原位)
- (IBAction)moveAtPath:(id)sender {
//設置keyPath 為:transform.translation.x
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
animation.fromValue= @(150);
animation.toValue = @(-150);
animation.duration=1;
//不回到原位置,但是控件的“真身”還在原位
animation.removedOnCompletion=NO;
//保持的狀態
animation.fillMode=kCAFillModeForwards;
[self.button.layer addAnimation:animation forKey:nil];
}
#pragma mark - 基本動畫:旋轉
- (IBAction)rotate:(UIButton *)sender {
//設置keyPath 為:transform.rotation.y
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
//轉一周
NSNumber * num = @(M_PI*2);
animation.toValue=num;
animation.removedOnCompletion=NO;
animation.fillMode=kCAFillModeForwards;
//轉了3秒
animation.duration=3;
//重復次數無限大
animation.repeatCount=CGFLOAT_MAX;
[self.button.layer addAnimation:animation forKey:nil];
}
五、CAKeyframeAnimation 關鍵幀動畫
1、定義:
關鍵幀動畫,也是CApropertyAnimation的子類。通過設置keyPath,多個值之間的變化實現動畫。
2、屬性解析:
3、 與CABasicAnimation的區別:
4、代碼案例
#pragma mark - 關鍵幀:按方形路徑移動
- (IBAction)keyPathPath:(UIButton *)sender {
//設置keyPath 為:position
CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//設置5個值
NSValue * v1 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSValue * v2 = [NSValue valueWithCGPoint:CGPointMake(100, 400)];
NSValue * v3 =[NSValue valueWithCGPoint:CGPointMake(300, 400)];
NSValue * v4 = [NSValue valueWithCGPoint:CGPointMake(300, 200)];
NSValue * v5 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
//加入“值”數組
animation.values=@[v1,v2,v3,v4,v5];
animation.duration=2;
animation.repeatCount=CGFLOAT_MAX;
animation.removedOnCompletion=NO;
animation.fillMode=kCAFillModeForwards;
[self.button.layer addAnimation:animation forKey:nil];
}
#pragma mark - 關鍵幀:size變化
- (IBAction)keyPathSize:(id)sender {
//設置keyPath 為:bounds.size
CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"bounds.size"];
//設置三個值
NSValue * v0 = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
NSValue * v1 = [NSValue valueWithCGSize:CGSizeMake(200, 200)];
NSValue * v2 = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
animation.values=@[v0,v1,v2];
animation.duration=0.5;
animation.repeatCount=CGFLOAT_MAX;
animation.removedOnCompletion=NO;
animation.fillMode=kCAFillModeForwards;
[self.button.layer addAnimation:animation forKey:nil];
}
#pragma mark - 關鍵幀:抖動
- (IBAction)keyPathShake:(id)sender {
//設置keyPath 為:transform.rotation.z
CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
//設置兩個角度值
NSNumber * n1 = @(-M_PI_4/3);
NSNumber * n2 = @(M_PI_4/3);
//再三個值之間進行改變
animation.values=@[n1,n2,n1,];
animation.repeatCount=CGFLOAT_MAX;
animation.duration=0.15;
animation.removedOnCompletion=NO;
animation.fillMode=kCAFillModeForwards;
[self.button.layer addAnimation:animation forKey:nil];
}
六、CAAnimationGroup 組動畫
1、定義:
2、屬性解析:
3、代碼案例
給出一個組動畫和轉場動畫的基本配置案例
效果:

#pragma mark - 組動畫
- (IBAction)groupAnimation:(UIButton *)sender {
[self makeView:nil];
//動畫1:移動
CAKeyframeAnimation * animation1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSValue * v1 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSValue * v2 = [NSValue valueWithCGPoint:CGPointMake(100, 400)];
NSValue * v3 = [NSValue valueWithCGPoint:CGPointMake(300, 400)];
NSValue * v4 = [NSValue valueWithCGPoint:CGPointMake(300, 200)];
NSValue * v5 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
animation1.values=@[v1,v2,v3,v4,v5];
animation1.repeatCount=CGFLOAT_MAX;
animation1.removedOnCompletion=NO;
animation1.fillMode=kCAFillModeForwards;
//動畫2 :
CAKeyframeAnimation * animation2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
NSNumber * n1 = @(-M_PI_4/2);
NSNumber * n2 = @(M_PI_4/2);
animation2.values=@[n1,n2,n1,];
animation2.repeatCount=CGFLOAT_MAX;
animation2.duration=0.15;
animation2.removedOnCompletion=NO;
animation2.fillMode=kCAFillModeForwards;
//創建組動畫
CAAnimationGroup * animation = [CAAnimationGroup animation];
animation.animations=@[animation1,animation2];
animation.duration=2;
animation.repeatCount=CGFLOAT_MAX;
//將組動畫加入到layer就可以了,各個動畫並發執行
[self.button.layer addAnimation:animation forKey:nil];
}
七、CATransition 轉場動畫
1、定義:
轉場動畫,CAAnimation的子類,用於做頁面跳轉時的轉場動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。UINavigationController就是通過CATransition實現了將控制器的視圖推入屏幕的動畫效果。這些動畫的效果系統已經寫好,我們只要配置一些屬性即可。
2、屬性解析:
3、代碼案例(這裡把下面的UIView動畫一起實現,方便比較)
#pragma mark - 轉場動畫
-(void)makeImage
{
//生成一個測試轉場動畫的視圖
UIImageView * imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1"]];
imageView.center =self.view.center;
self.imageView=imageView;
[self.view addSubview: imageView];
//創建手勢識別器,用來響應屏幕滑動
UISwipeGestureRecognizer * swipeLeft = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeImage:)];
UISwipeGestureRecognizer * swipeRight =[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeImage:)];
//添加識別器屬性
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
//添加到視圖
[self.view addGestureRecognizer:swipeLeft];
[self.view addGestureRecognizer:swipeRight];
}
#pragma mark - 滑動屏幕響應事件
-(void)swipeImage:(UISwipeGestureRecognizer *)rec
{
//判斷滑動方向
//向左滑動
if (rec.direction==UISwipeGestureRecognizerDirectionLeft) {
self.index++;
//圖片可以循環播放
if (self.index==6) {
self.index=1;
}
}
//向右滑動
else{
self.index--;
if (self.index==0) {
self.index=5;
}
}
#pragma mark - 方式一,使用過CATransition實現轉場(漸變消失)
//這裡的changeStyle只是點擊按鈕的判斷
if (self.changeStyle==1) {
//創建動畫
CATransition * animation = [CATransition animation];
//前一張消失
animation.type = kCATransitionFade;
//將動畫添加到控件layer,控件屬性變化時(圖片更換)將采用設定動畫
[self.imageView.layer addAnimation:animation forKey:nil];
}
#pragma mark - 方式二 ,使用UIView(block)實現轉場(向左拖:左右旋轉+ 向右拖:上下翻頁)
else if(self.changeStyle==2) {
//如果向左滑動,向左旋轉顯示
if (rec.direction==UISwipeGestureRecognizerDirectionLeft) {
[UIView transitionWithView:self.imageView duration:1 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
//block裡面是控件的屬性變化,這裡和CATransition實現不同
UIImage * image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld",self.index]];
self.imageView.image=image;
} completion:nil];
}
//如果向右滑動,子頁面向下推出
else{
[UIView transitionWithView:self.imageView duration:1 options:UIViewAnimationOptionTransitionCurlUp animations:^{
UIImage * image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld",self.index]];
self.imageView.image=image;
} completion:nil];
}
}
#pragma mark - 方式三,使用過CATransition實現轉場(向左滑:向左退出 + 向右滑:向下推出)
else{
CATransition * animation = [CATransition animation];
//如果向右滑動,子頁面從左推出
if (rec.direction == UISwipeGestureRecognizerDirectionRight) {
animation.subtype = kCATransitionFromBottom;
}
//如果向右滑動,子頁面從下推出
else{
animation.subtype = kCATransitionFromRight;
}
animation.type = kCATransitionPush;
[self.imageView.layer addAnimation:animation forKey:nil];
}
UIImage * image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld",self.index]];
//這是添加了動畫的控件,屬性改變時按照我們設定的有動畫效果
self.imageView.image=image;
}
八、UIView block動畫———(也可實現轉場動畫)
1、定義:
UIKit框架直接將動畫集成到UIView類中,當內部的一些屬性發生改變時,UIView將為這些改變提供動畫支持。
2、UIView動畫的幾種類別:
(1)三種block方式實現:所謂block方式,就是將改變視圖屬性的代碼寫在block中,實現動畫
參數解析:
duration: 動畫的持續時間
delay: 動畫延遲delay秒後開始
options: 動畫的節奏控制
animations: 將改變視圖屬性的代碼放在這個block中
completion: 動畫結束後,會自動調用這個block
參數解析:
duration: 動畫的持續時間
view: 需要進行轉場動畫的視圖
options: 轉場動畫的類型
animations: 將改變視圖屬性的代碼放在這個block中
completion: 動畫結束後,會自動調用這個block
方法調用完畢後,相當於執行了下面兩句代碼:
// 添加toView到父視圖
[fromView.superview addSubview:toView];
// 把fromView從父視圖中移除
[fromView.superview removeFromSuperview];
參數解析:
duration: 動畫的持續時間
options: 轉場動畫的類型
animations: 將改變視圖屬性的代碼放在這個block中
completion: 動畫結束後,會自動調用這個block
(2)首尾式動畫等(下文單獨介紹)。
九、UIView 首尾式動畫
1、定義:
UIView的另一種實現動畫方式。
2、執行方式:
執行動畫所需要的工作由UIView類自動完成,但仍要在希望執行動畫時通知視圖,為此需要將改變屬性的代碼放在[UIView beginAnimations:nil context:nil]和[UIView commitAnimations]之間,俗稱首尾式動畫。
3、常見方法解析:
設置動畫代理對象,當動畫開始或者結束時會發消息給代理對象
當動畫即將開始時,執行delegate對象的selector,並且把beginAnimations:context:中傳入的參數傳進selector
當動畫結束時,執行delegate對象的selector,並且把beginAnimations:context:中傳入的參數傳進selector
動畫的持續時間,秒為單位
動畫延遲delay秒後再開始
動畫的開始時間,默認為now
動畫的節奏控制,具體看下面的”備注”
動畫的重復次數
如果設置為YES,代表動畫每次重復執行的效果會跟上一次相反
設置視圖view的過渡效果, transition指定過渡類型, cache設置YES代表使用視圖緩存,性能較好
九、UIImageView的幀動畫
1、定義:
UIImageView可以讓一系列的圖片在特定的時間內按順序顯示。
2、屬性解析:
3、方法解析:
十、UIActivityIndicatorView 轉輪動畫
1、定義:
是一個旋轉進度輪,可以用來告知用戶有一個操作正在進行中,一般用initWithActivityIndicatorStyle初始化(之前的文章有做介紹)。
2、方法解析:
UIActivityIndicatorViewStyleWhiteLarge //大型白色指示器
UIActivityIndicatorViewStyleWhite //標准尺寸白色指示器
UIActivityIndicatorViewStyleGray //灰色指示器,用於白色背景
總結:
一款優秀的app離不開良好的用戶體驗,在現在用戶越來越挑剔,設計模式越來越成熟和泛濫的情況下,第一時間抓住用戶的眼球,自然是會獲得更高的成功率。另外,界面的多元化,也帶來了很多其他的使用功能,在賞心悅目的同時,也增加了app的功能擴展。所以,在膜拜大神們華麗設計的同時,自己也不妨嘗試給自己的設計加點花樣。。有了畫筆,剩下的靠自己~