iOS核心動畫以及UIView動畫的介紹

咱們看到不少App帶有絢麗狂拽的特效,別出心裁的控件設計,很大程度上提升了用戶體驗,在增長了實用性的同時,也賦予了app無限的生命力。這些華麗的效果不少都是基於iOS的核心動畫原理實現的,本文介紹一些iOS開發中最基本的動畫效果實現,掌握了基本屬性,才能夠繪製出更華麗的效果。設計模式

 

1、概念擴充數組

 一、核心動畫:緩存

  Core Animation,它是一組很是強大的動畫處理API,使用它能作出很是炫麗的動畫效果,並且每每是事半功倍。 Core Animation能夠用在Mac OS X和iOS平臺。在iOS平臺中,動畫效果會略少一些。另外,iOS開發中實現動畫的方式也不僅是核心動畫一種,後面會介紹UIView的幾種動畫。併發

 二、執行和建立動畫過程:app

 (1)Core Animation的動畫執行過程都是在後臺操做的,不會阻塞主線程。要注意的是,Core Animation是直接做用在CALayer上的,並不是UIView。因此,CALayer是核心動畫的基礎。框架

 (2)關於框架:iOS7之後,再也不須要導入QuartzCore.framework框架和主頭文件<QuartzCore/QuartzCore.h>函數

 (3)基本的建立動畫流程性能

  •   建立動畫對象;
  •   設置動畫屬性;
  •   把動畫對象添加到某個 CALayer 對象上;
  •   須要中止動畫:能夠調用 remove 方法移除動畫。

三、動畫類型:後面作詳細的使用介紹測試

  •   屬性動畫:設定某個屬性的值,能夠實現屬性動畫。
  •   基本動畫(CABasicAnimation):設定某個屬性從某個值到某個值,實現基本動畫。
  •   關鍵幀動畫(CAKeyframeAnimation):設定某個屬性的值從某個值到某個值,再到某個值。按照關鍵值改變的順序,實現動畫。  
  •   組動畫(CAAnimationGroup):把全部其餘的動畫添加到組裏面,這樣就能夠按照添加的動畫一次執行。
  •   轉場動畫(CATransition):從一個場景轉換到另外一個場景,系統已經實現好了,不須要咱們再去寫,按照需求直接調用。

 

四、本質與繼承關係動畫

(1)本質:在後臺移動圖層中的內容,  執行完畢後圖層自己的位置並無發生變化。

(2)全部的動畫都繼承自CAAnimation

 

 

2、CAAnimation

 

一、定義:

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

二、 屬性解析:(不少屬性都是來自CAMediaTiming協議)

  • duration:        動畫的持續時間,默認0.25s
  • repeatCount:      動畫的重複次數
  • repeatDuration: 動畫的重複時間
  • removedOnCompletion:默認爲YES,表明動畫執行完畢後就從圖層上移除,圖形會恢復到動畫執行前的狀態。若是想讓圖層保持顯示動畫執行後的狀態,那就設置爲NO,不過還要設置fillMode爲kCAFillModeForwards
  • fillMode:決定當前對象在非active時間段的行爲.好比動畫開始以前,動畫結束以後
  • beginTime:能夠用來設置動畫延遲執行時間,若想延遲2s,就設置爲CACurrentMediaTime()+2,CACurrentMediaTime()爲圖層的當前時間
  • timingFunction:速度控制函數,控制動畫運行的節奏

 三、隱式代理:delegate

 (1)  CAAnimation有一個id類型的delegate屬性,可是此屬性沒有遵照任何協議,自己也沒有任何代理協議。

 (2)  實現代理方法:注意,這裏的兩個方法,是在NSObject擴展中聲明的,因此是自己就是NSObject的方法,每個類都能實現該方法。o(╯□╰)o。。

  • 監聽動畫開始   -(void)animationDidStart:(CAAnimation *)anim  
  • 監聽動畫結束   - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;  

 (3)給CAAnimation的delegate賦值(說明誰來代理)、重寫代理方法,就能夠實現「隱式」代理。

 

3、CAPropertyAnimation

 

一、定義:

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

二、屬性解析:

  • keyPath:將CALayer的一個屬性名稱做爲keyPath(NSString類型),而且對CALayer的這個屬性的值進行修改,達到相應的動畫效果。好比,指定@」position」爲keyPath,就修改CALayer的position屬性的值,以達到平移的動畫效果。下面三張圖是官方給出的keyPath:

(1)圖1:position屬性———CGPoint類型

 

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

 

 

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

 

 

4、CABasicAnimation 基本動畫

 

一、定義:

   基本動畫,CAPropertyAnimation的子類。經過設置keyPath,兩個值之間的變化實現動畫。

二、屬性解析: 

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

  隨着動畫的進行,在長度爲duration的持續時間內,keyPath相應屬性的值從fromValue漸漸地變爲toValue,若是fillMode=kCAFillModeForwardsremovedOnComletion=NO,那麼在動畫執行完畢後,圖層會保持顯示動畫執行後的狀態。但在實質上,圖層的屬性值仍是動畫執行前的初始值,並無真正被改變。好比,CALayer的position初始值爲(0,0),CABasicAnimation的fromValue爲(10,10),toValue爲(100,100),雖然動畫執行完畢後圖層保持在(100,100)這個位置,實質上圖層的position仍是爲(0,0)

 

三、代碼案例:

  給出一個基本動畫和關鍵幀動畫的基本配置案例

  效果:

     

 

#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];
    
}

 

5、CAKeyframeAnimation 關鍵幀動畫

 

一、定義:

   關鍵幀動畫,也是CApropertyAnimation的子類。經過設置keyPath,多個值之間的變化實現動畫。

二、屬性解析:

  • values:就是上述的NSArray對象。裏面的元素稱爲」關鍵幀」(keyframe)。動畫對象會在指定的時間(duration)內,依次顯示values數組中的每個關鍵幀。
  • path:能夠設置一個CGPathRef\CGMutablePathRef,讓層跟着路徑移動。path只對CALayer的anchorPoint和position起做用。若是你設置了path,那麼values將被忽略。
  • keyTimes:能夠爲對應的關鍵幀指定對應的時間點,其取值範圍爲0到1.0,keyTimes中的每個時間值都對應values中的每一幀.當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的。

 

三、 與CABasicAnimation的區別:

  •  CABasicAnimation只能從一個數值(fromValue)變到另外一個數值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數值。CABasicAnimation可看作是最多隻有2個關鍵幀的CAKeyframeAnimation。

四、代碼案例

#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];
    
}

 

6、CAAnimationGroup 組動畫

 

一、定義:

  • 組動畫,是CAAnimation的子類,能夠保存一組動畫對象,將CAAnimationGroup對象加入層後,組中全部動畫對象能夠同時併發運行。

 二、屬性解析:

  • animations:用來保存一組動畫對象的NSArray。
  • 默認狀況下,一組動畫對象是同時運行的,也能夠經過設置動畫對象的beginTime屬性來更改動畫的開始時間。

三、代碼案例

  給出一個組動畫和轉場動畫的基本配置案例

   效果:

    

 

#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];
    
}

 

 

7、CATransition 轉場動畫

 

一、定義:

  轉場動畫,CAAnimation的子類,用於作頁面跳轉時的轉場動畫,可以爲層提供移出屏幕和移入屏幕的動畫效果。UINavigationController就是經過CATransition實現了將控制器的視圖推入屏幕的動畫效果。這些動畫的效果系統已經寫好,咱們只要配置一些屬性便可。

 

二、屬性解析:

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

三、代碼案例(這裏把下面的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;
    
}

 

 

8、UIView block動畫———(也可實現轉場動畫)

 

一、定義:

   UIKit框架直接將動畫集成到UIView類中,當內部的一些屬性發生改變時,UIView將爲這些改變提供動畫支持。

 

二、UIView動畫的幾種類別:

 (1)三種block方式實現:所謂block方式,就是將改變視圖屬性的代碼寫在block中,實現動畫

  • + (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion  

    參數解析:

    duration:   動畫的持續時間 

    delay    動畫延遲delay秒後開始  

    options   動畫的節奏控制

    animations 將改變視圖屬性的代碼放在這個block中

    completion 動畫結束後,會自動調用這個block

  • + (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion

     參數解析:

    duration:   動畫的持續時間

    view:     須要進行轉場動畫的視圖

    options:    轉場動畫的類型

    animations:  將改變視圖屬性的代碼放在這個block中

    completion:  動畫結束後,會自動調用這個block

  • + (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion

     方法調用完畢後,至關於執行了下面兩句代碼:

    // 添加toView到父視圖

      [fromView.superview addSubview:toView]; 

    // 把fromView從父視圖中移除

      [fromView.superview removeFromSuperview];

    參數解析:

    duration:   動畫的持續時間

    options:   轉場動畫的類型

    animations:  將改變視圖屬性的代碼放在這個block中

    completion:  動畫結束後,會自動調用這個block

(2)首尾式動畫等(下文單獨介紹)。

 

9、UIView 首尾式動畫

 

一、定義:

  UIView的另外一種實現動畫方式。

二、執行方式:

  執行動畫所須要的工做由UIView類自動完成,但仍要在但願執行動畫時通知視圖,爲此須要將改變屬性的代碼放在[UIView beginAnimations:nil context:nil]和[UIView commitAnimations]之間,俗稱首尾式動畫。

 

三、常見方法解析:

  • + (void)setAnimationDelegate:(id)delegate

  設置動畫代理對象,當動畫開始或者結束時會發消息給代理對象

  • + (void)setAnimationWillStartSelector:(SEL)selector

  當動畫即將開始時,執行delegate對象的selector,而且把beginAnimations:context:中傳入的參數傳進selector

  • + (void)setAnimationDidStopSelector:(SEL)selector

  當動畫結束時,執行delegate對象的selector,而且把beginAnimations:context:中傳入的參數傳進selector

  • + (void)setAnimationDuration:(NSTimeInterval)duration

  動畫的持續時間,秒爲單位

  • + (void)setAnimationDelay:(NSTimeInterval)delay

  動畫延遲delay秒後再開始

  • + (void)setAnimationStartDate:(NSDate *)startDate

  動畫的開始時間,默認爲now

  • + (void)setAnimationCurve:(UIViewAnimationCurve)curve

  動畫的節奏控制,具體看下面的」備註」

  • + (void)setAnimationRepeatCount:(float)repeatCount

  動畫的重複次數

  • + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses

  若是設置爲YES,表明動畫每次重複執行的效果會跟上一次相反

  • + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache

  設置視圖view的過渡效果, transition指定過渡類型, cache設置YES表明使用視圖緩存,性能較好

 

9、UIImageView的幀動畫

 

一、定義:

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

二、屬性解析:

  • animationImages:要顯示的圖片(一個裝着UIImage的NSArray)
  • animationDuration:完整地顯示一次animationImages中的全部圖片所需的時間
  • animationRepeatCount:動畫的執行次數(默認爲0,表明無限循環)

三、方法解析:

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

 

10、UIActivityIndicatorView 轉輪動畫

 

一、定義:

   是一個旋轉進度輪,能夠用來告知用戶有一個操做正在進行中,通常用initWithActivityIndicatorStyle初始化(以前的文章有作介紹)

 二、方法解析:

  • - (void)startAnimating; 開始動畫
  • - (void)stopAnimating;  中止動畫
  • - (BOOL)isAnimating;  是否正在運行動畫
  • UIActivityIndicatorViewStyle  有3個值可供選擇:

    UIActivityIndicatorViewStyleWhiteLarge    //大型白色指示器    

    UIActivityIndicatorViewStyleWhite             //標準尺寸白色指示器    

    UIActivityIndicatorViewStyleGray               //灰色指示器,用於白色背景

 

總結:

一款優秀的app離不開良好的用戶體驗,在如今用戶愈來愈挑剔,設計模式愈來愈成熟和氾濫的狀況下,第一時間抓住用戶的眼球,天然是會得到更高的成功率。另外,界面的多元化,也帶來了不少其餘的使用功能,在賞心悅目的同時,也增長了app的功能擴展。因此,在膜拜大神們華麗設計的同時,本身也不妨嘗試給本身的設計加點花樣。。有了畫筆,剩下的靠本身~

相關文章
相關標籤/搜索