我們看到很多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的功能擴展。所以,在膜拜大神們華麗設計的同時,自己也不妨嘗試給自己的設計加點花樣。。有了畫筆,剩下的靠自己~