史上最全-iOS開發中所用的動畫 效果看這裏就夠了

前言

上次總結了多線程的用法,這次再複習下的iOS動畫的東西。這次依然先是以API爲主,因爲好多人還是API好多的東西還不會用。然後中間穿插些例子,例子和代碼文章中都會有。因爲篇幅比較長,先列一下大綱。

動畫的繼承結構

CAAnimation{
     CAPropertyAnimation{
            CABasicAnimation{
                    CASpringAnimation
            }
            CAKeyframeAnimation
     }
     CATransition   
     CAAnimationGroup
}

CAAnimation(動畫根類,不可以直接使用)


CAAnimation-屬性(複雜點的屬性,下面會有詳細解釋)

//動畫的代理回調,下面會有
@property(nullable, strong) id delegate;
//動畫執行完以後是否移除動畫,默認YES
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
//動畫的動作規則,包含以下值
//kCAMediaTimingFunctionLinear 勻速
//kCAMediaTimingFunctionEaseIn 慢進快出
//kCAMediaTimingFunctionEaseOut 快進慢出
//kCAMediaTimingFunctionEaseInEaseOut 慢進慢出 中間加速
//kCAMediaTimingFunctionDefault 默認
@property(nullable, strong) CAMediaTimingFunction *timingFunction;

以上屬性的詳解:

  • 委託:動畫執行的代理,在動畫開始前設定,不用顯式的寫在代碼裏,它包含兩個方法:
    動畫開始回調
    - (void)animationDidStart:(CAAnimation *)anim;
    動畫結束回調
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
  • removedOnCompletion:動畫完成後是否移除動畫默認爲YES此屬性爲YES時,在fillMode不可用,具體爲什麼不可用,可以自己結合兩個屬性分析一下,這裏不再贅述。
  • timingFunction設置動畫速度曲線,默認值上面已經給出下面說它的幾個方法:
    。這兩個方法是一樣的如果我們對系統自帶的速度函數不滿意,可以通過這兩個函數創建一個自己喜歡的速度曲線函數,具體用法可以參考這篇文章CAMediaTimingFunction使用的
    + (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
    - (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;
    電子雜誌曲線的函數的緩衝點,具體用法可以參考這篇文章:iOS-核心動畫高級編程/ 10-緩衝
    - (void)getControlPointAtIndex:(size_t)idx values:(float[2])ptr;

CAAnimation <CAMediaTiming>協議的屬性

//開始時間.這個屬性比較複雜,傻瓜用法爲:CACurrentMediaTime() + x,
//其中x爲延遲時間.如果設置 beginTime = CACurrentMediaTime() + 1.0,產生的效果爲延遲一秒執行動畫,下面詳解原理
@property CFTimeInterval beginTime;
//動畫執行時間,此屬性和speed有關係speed默認爲1.0,如果speed設置爲2.0,那麼動畫執行時間則爲duration*(1.0/2.0).
@property CFTimeInterval duration;
//動畫執行速度,它duration的關係參考上面解釋
@property float speed;
//動畫的時間延遲,這個屬性比較複雜,下面詳解
@property CFTimeInterval timeOffset;
//重複執行次數
@property float repeatCount;
//重複執行時間,此屬性優先級大於repeatCount.也就是說如果repeatDuration設置爲1秒重複10次,那麼它會在1秒內執行完動畫.
@property CFTimeInterval repeatDuration;
//是否自動翻轉動畫,默認NO.如果設置YES,那麼整個動畫的執行效果爲A->B->A.
@property BOOL autoreverses;
//動畫的填充方式,默認爲: kCAFillModeRemoved,包含以下值
//kCAFillModeForwards//動畫結束後回到準備狀態
//kCAFillModeBackwards//動畫結束後保持最後狀態
//kCAFillModeBoth//動畫結束後回到準備狀態,並保持最後狀態
//kCAFillModeRemoved//執行完成移除動畫
@property(copy) NSString *fillMode;

以上屬性的詳解:

  • BEGINTIME:剛纔上面簡單解釋了下這個屬性的用法:CACurrentMediaTime()+ x。會使動畫延遲執行點¯x秒不知道到這裏有沒有人想過如果-x?會出現怎麼樣效果假設我們有執行一個3秒的動畫,設置然後beginTime = CACurrentMediaTime()- 1.5那麼執行動畫你會發現動畫只會執行後半段,就是也。只執行後面的3-1.5s的動畫。爲什麼會這樣?其實動畫都有一個時間表(時間線)的概念。動畫開始執行都是基於這個時間線的絕對時間,這個時間和它的父類有關(系統的屬性註釋可以看到)。默認的CALayer的的BEGINTIME爲零,如果這個值爲零的話,系統會把它設置爲CACurrentMediaTime(),那麼這個時間就是正常執行動畫的時間:立即執行所以如果設置你beginTime=CACurrentMediaTime()+x;它會把它的執行時間線推遲x秒,就是也。晚執行x秒,如果你beginTime=CACurrentMediaTime()-x;那它開始的時候會從你動畫對應的絕對時間開始執行。
  • timeOffset:時間偏移量,默認爲0;既然它是時間偏移量,那麼它即和動畫時間相關這麼解釋:假設我們設置一個動畫時間爲5秒,動畫執行的過程爲1->2->3->4->5,這時候如果你設置timeOffset = 2s它那麼的執行過程就會變成3->4->5->1->2如果你設置timeOffset = 4s那麼它的執行過程就會變成5->1->2->3->4,這麼說應該很明白了吧?

CAPropertyAnimation屬性動畫,抽象類,不能直接使用

CAPropertyAnimation的屬性

//需要動畫的屬性值
@property(nullable, copy) NSString *keyPath;
//屬性動畫是否以當前動畫效果爲基礎,默認爲NO
@property(getter=isAdditive) BOOL additive;
//指定動畫是否爲累加效果,默認爲NO
@property(getter=isCumulative) BOOL cumulative;
//此屬性相當於CALayer中的transform屬性,下面會詳解
@property(nullable, strong) CAValueFunction *valueFunction;

以上屬性的詳解:

CAPropertyAnimation是屬性動畫顧名思義也就是針對屬性纔可以做的動畫那它可以對誰的屬性可以做動畫是的CALayer的屬性,比如:?界限,位置等那麼問題來了,我們改變的CALayer的位置可以。設置直接[CAPropertyAnimation animationWithKeyPath:@"position"]如果我們設置它的變換(CATransform3D)呢?CATransform3D是一個矩陣,如果我們想爲它做動畫怎麼辦?下面這個屬性就是用來解決這個問題的。

  • valueFunction:我們來看它可以設置的值:
    kCAValueFunctionRotateX
    kCAValueFunctionRotateY
    kCAValueFunctionRotateZ
    kCAValueFunctionScale
    kCAValueFunctionScaleX
    kCAValueFunctionScaleY
    kCAValueFunctionScaleZ
    kCAValueFunctionTranslate
    kCAValueFunctionTranslateX
    kCAValueFunctionTranslateY
    kCAValueFunctionTranslateZ
    說到這裏大家應該都知道該怎麼用了吧〜。

CAPropertyAnimation的方法

//通過key創建一個CAPropertyAnimation對象
+ (instancetype)animationWithKeyPath:(nullable NSString *)path;

下面我們來看一下可以設置屬性動畫的屬性歸總:

CATransform3D{
    rotation旋轉
    transform.rotation.x
    transform.rotation.y
    transform.rotation.z

    scale縮放
    transform.scale.x
    transform.scale.y
    transform.scale.z

    translation平移
    transform.translation.x
    transform.translation.y
    transform.translation.z
}

CGPoint{
    position
    position.x
    position.y
}

CGRect{
    bounds
    bounds.size
    bounds.size.width
    bounds.size.height

    bounds.origin
    bounds.origin.x
    bounds.origin.y
}

property{
    opacity
    backgroundColor
    cornerRadius
    borderWidth
    contents

    Shadow{
        shadowColor
        shadowOffset
        shadowOpacity
        shadowRadius
    }
}

總結:CAAnimation是基類,CAPropertyAnimation是抽象類,兩者都不可以直接使用,那我們只有使用它的子類了。

CABasicAnimation基本動畫

CABasicAnimation的屬性

//開始值
@property(nullable, strong) id fromValue;
//結束值
@property(nullable, strong) id toValue;
//結束值
@property(nullable, strong) id byValue;

這三個屬性之間的規則

  • fromValue狀語從句:toValue不爲空,的動畫會效果從fromValue的值變化到toValue
  • fromValue狀語從句:byValue都不爲空,的動畫效果將會從fromValue變化到fromValue+byValue
  • toValue狀語從句:byValue都不爲空,的動畫效果將會從toValue-byValue變化到toValue
  • 只有fromValue的值不爲空,的動畫效果將會從fromValue的值變化到當前的狀態。
  • 只有toValue的值不爲空,的動畫效果將會從當前狀態的值變化到toValue的值。
    只有byValue的值不爲空,動畫的效果將會從當前的值變化到(當前狀態的值+ byValue)的值。

CABasicAnimation看起來不太複雜,但實際只用這個就足以可以做很多種動畫了,下面簡單用一下,先看效果:


CABasicAnimation.gif

然後再看下實現代碼:

#import "ViewController.h"
#import "TFEasyCoder.h"
@interface ViewController ()

@property (nonatomic,strong)UIView *demoView;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    kdeclare_weakself;
    NSArray *titles = @[@"淡入淡出",@"縮放",@"旋轉",@"平移"];
    for (unsigned int i = 0; i < titles.count; i++) {

        [UIButton easyCoder:^(UIButton *ins) {
            [weakSelf.view addSubview:ins];
            ins.backgroundColor = [UIColor brownColor];
            ins.tag = i;
            ins.frame = CGRectMake(10, 50 + 80 * i, 100, 60);
            [ins setTitle:titles[i] forState:UIControlStateNormal];
            [ins addTarget:self action:@selector(animationBegin:) forControlEvents:UIControlEventTouchUpInside];
        }];
    }


    [UIView easyCoder:^(UIView *ins) {

        ins.frame = CGRectMake(0, 0, 100, 100);
        ins.backgroundColor = [UIColor redColor];
        ins.center = self.view.center;

        weakSelf.demoView = ins;
        [weakSelf.view addSubview:weakSelf.demoView];
    }];



}

-(void)animationBegin:(UIButton *)btn{
    CABasicAnimation *animation = nil;
    switch (btn.tag) {
        case 0:{
            //淡如淡出
            animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
            [animation setFromValue:@1.0];
            [animation setToValue:@0.1];
        }break;
        case 1:{
            //縮放
            animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
            [animation setFromValue:@1.0];//設置起始值
            [animation setToValue:@0.1];//設置目標值
        }break;
        case 2:{
            //旋轉
            animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
            //setFromValue不設置,默認以當前狀態爲準
            [animation setToValue:@(M_PI)];
        }break;
        case 3:{
            //平移
            animation = [CABasicAnimation animationWithKeyPath:@"position"];
            //setFromValue不設置,默認以當前狀態爲準
            [animation setToValue:[NSValue valueWithCGPoint:CGPointMake(self.view.center.x, self.view.center.y + 200)]];
        }break;
        default:break;
    }
    [animation setDelegate:self];//代理回調
    [animation setDuration:0.25];//設置動畫時間,單次動畫時間
    [animation setRemovedOnCompletion:NO];//默認爲YES,設置爲NO時setFillMode有效
    /**
     *設置時間函數CAMediaTimingFunction
     *kCAMediaTimingFunctionLinear 勻速
     *kCAMediaTimingFunctionEaseIn 開始速度慢,後來速度快
     *kCAMediaTimingFunctionEaseOut 開始速度快 後來速度慢
     *kCAMediaTimingFunctionEaseInEaseOut = kCAMediaTimingFunctionDefault 中間速度快,兩頭速度慢
     */
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    //設置自動翻轉
    //設置自動翻轉以後單次動畫時間不變,總動畫時間增加一倍,它會讓你前半部分的動畫以相反的方式動畫過來
    //比如說你設置執行一次動畫,從a到b時間爲1秒,設置自動翻轉以後動畫的執行方式爲,先從a到b執行一秒,然後從b到a再執行一下動畫結束
    [animation setAutoreverses:YES];
    //kCAFillModeForwards//動畫結束後回到準備狀態
    //kCAFillModeBackwards//動畫結束後保持最後狀態
    //kCAFillModeBoth//動畫結束後回到準備狀態,並保持最後狀態
    //kCAFillModeRemoved//執行完成移除動畫
    [animation setFillMode:kCAFillModeBoth];
    //將動畫添加到layer,添加到圖層開始執行動畫,
    //注意:key值的設置與否會影響動畫的效果
    //如果不設置key值每次執行都會創建一個動畫,然後創建的動畫會疊加在圖層上
    //如果設置key值,系統執行這個動畫時會先檢查這個動畫有沒有被創建,如果沒有的話就創建一個,如果有的話就重新從頭開始執行這個動畫
    //你可以通過key值獲取或者刪除一個動畫:
    //[self.demoView.layer animationForKey:@""];
    //[self.demoView.layer removeAnimationForKey:@""]
    [self.demoView.layer addAnimation:animation forKey:@"baseanimation"];
}

/**
 *  動畫開始和動畫結束時 self.demoView.center 是一直不變的,說明動畫並沒有改變視圖本身的位置
 */
- (void)animationDidStart:(CAAnimation *)anim{
    NSLog(@"動畫開始------:%@",    NSStringFromCGPoint(self.demoView.center));
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    NSLog(@"動畫結束------:%@",    NSStringFromCGPoint(self.demoView.center));
}

以上效果和代碼還有註釋都解釋的很詳細了,然後源碼在這裏:人口統計學基本動畫

CASpringAnimation彈性動畫

CASpringAnimation的屬性(iOS9新加)

//理解下面的屬性的時候可以結合現實物理現象,比如把它想象成一個彈簧上掛着一個金屬小球
//質量,振幅和質量成反比
@property CGFloat mass;
//剛度係數(勁度係數/彈性係數),剛度係數越大,形變產生的力就越大,運動越快
@property CGFloat stiffness;
//阻尼係數,阻止彈簧伸縮的係數,阻尼係數越大,停止越快,可以認爲它是阻力系數
@property CGFloat damping;
//初始速率,動畫視圖的初始速度大小速率爲正數時,速度方向與運動方向一致,速率爲負數時,速度方向與運動方向相反.
@property CGFloat initialVelocity;
//結算時間,只讀.返回彈簧動畫到停止時的估算時間,根據當前的動畫參數估算通常彈簧動畫的時間使用結算時間比較準確
@property(readonly) CFTimeInterval settlingDuration;

下面我們寫一個演示看看效果:


彈簧彈性動畫.gif注意

以上GIF的代碼爲:

CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"position.y"];
spring.damping = 5;
spring.stiffness = 100;
spring.mass = 1;
spring.initialVelocity = 0;
spring.duration = spring.settlingDuration;
spring.fromValue = @(self.demoView1.center.y);
spring.toValue = @(self.demoView1.center.y + (btn.selected?+200:-200));
spring.fillMode = kCAFillModeForwards;
[self.demoView1.layer addAnimation:spring forKey:nil];

CASpringAnimation效果不錯,但是很不幸只有iOS9 +系統才能使用,這就很操蛋了以前項目有過這樣的需求,然後就自己寫了一個類似的動畫,效果在下面:


自定義彈性動畫.gif注意

然後上面自定義彈性動畫的代碼在這裏:

#import "UIView+ShakeAnimation.h"
#import <objc/runtime.h>
typedef void (^RunAnimationBlock)();
@interface UIView ()
@property (nonatomic,  copy)RunAnimationBlock block;
@end

@implementation UIView (ShakeAnimation)

-(void)startAnimationFromFrame:(CGRect)framef
                       toFrame:(CGRect)framet
                      duration:(CGFloat)duration
                    shakeTimes:(NSInteger)times
                stretchPercent:(CGFloat)stretchPercent
                    completion:(void (^)(BOOL finished))completion
{
    self.layer.masksToBounds = YES;

    __block CGFloat perTime = duration / times;
    __block CGFloat perx = (framet.origin.x - framef.origin.x) * stretchPercent / times;
    __block CGFloat pery = (framet.origin.y - framef.origin.y) * stretchPercent / times;
    __block CGFloat perw = (framet.size.width - framef.size.width) * stretchPercent / times;
    __block CGFloat perh = (framet.size.height - framef.size.height) * stretchPercent / times;

    __block UIView * tmpView = self;
    __block NSInteger tmpTimes = (NSInteger)times;
    __block NSInteger tmpsymbol = -1;

    __weak typeof(self) weakSelf = self;
    self.block = ^{

        [UIView animateWithDuration:perTime animations:^{

            CGFloat x = framet.origin.x + perx * tmpTimes;
            CGFloat y = framet.origin.y + pery * tmpTimes;
            CGFloat w = framet.size.width + perw * tmpTimes;
            CGFloat h = framet.size.height + perh * tmpTimes;
            CGRect rect = CGRectMake(x, y, w, h);

            tmpView.frame = rect;
        }completion:^(BOOL finished) {

            tmpTimes = tmpTimes + tmpsymbol;
            tmpTimes = - tmpTimes;
            tmpsymbol = - tmpsymbol;
            if (tmpTimes != 0) {
                weakSelf.block();
            }else{
                [UIView animateWithDuration:perTime animations:^{
                    tmpView.frame = framet;
                }completion:^(BOOL finished) {
                    completion(YES);
                }];
            }
        }];
    };

    self.block();
}
static char RunAnimationBlockKey;
-(RunAnimationBlock)block{
    return objc_getAssociatedObject(self, &RunAnimationBlockKey);
}
-(void)setBlock:(RunAnimationBlock)block{
    objc_setAssociatedObject(self, &RunAnimationBlockKey, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end

調用:

[self.demoView2 startAnimationFromFrame:CGRectMake(10, 300, 100, 100)
                                toFrame:CGRectMake(10, 300, 300, 100)
                               duration:0.5
                             shakeTimes:5
                         stretchPercent:0.3
                             completion:^(BOOL finished) {
                                 NSLog(@"======over======:%@",self.demoView1);
                             }];

上面兩個彈性動畫的代碼在這裏:人口統計學彈性動畫

CAKeyframeAnimation關鍵幀動畫

CAKeyframeAnimation的屬性

//關鍵幀值數組,一組變化值
@property(nullable, copy) NSArray *values;
//關鍵幀幀路徑,優先級比values大
@property(nullable) CGPathRef path;
//每一幀對應的時間,時間可以控制速度.它和每一個幀相對應,取值爲0.0-1.0,不設則每一幀時間相等.
@property(nullable, copy) NSArray<NSNumber *> *keyTimes;
//每一幀對應的時間曲線函數,也就是每一幀的運動節奏
@property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;
//動畫的計算模式,默認值: kCAAnimationLinear.有以下幾個值:
//kCAAnimationLinear//關鍵幀爲座標點的時候,關鍵幀之間直接直線相連進行插值計算;
//kCAAnimationDiscrete//離散的,也就是沒有補間動畫
//kCAAnimationPaced//平均,keyTimes跟timeFunctions失效
//kCAAnimationCubic對關鍵幀爲座標點的關鍵幀進行圓滑曲線相連後插值計算,對於曲線的形狀還可以通過tensionValues,continuityValues,biasValues來進行調整自定義,keyTimes跟timeFunctions失效
//kCAAnimationCubicPaced在kCAAnimationCubic的基礎上使得動畫運行變得均勻,就是系統時間內運動的距離相同,,keyTimes跟timeFunctions失效
@property(copy) NSString *calculationMode;
//動畫的張力,當動畫爲立方計算模式的時候此屬性提供了控制插值,因爲每個關鍵幀都可能有張力所以連續性會有所偏差它的範圍爲[-1,1].同樣是此作用
@property(nullable, copy) NSArray<NSNumber *> *tensionValues;
//動畫的連續性值
@property(nullable, copy) NSArray<NSNumber *> *continuityValues;
//動畫的偏斜率
@property(nullable, copy) NSArray<NSNumber *> *biasValues;
//動畫沿路徑旋轉方式,默認爲nil.它有兩個值:
//kCAAnimationRotateAuto//自動旋轉,
//kCAAnimationRotateAutoReverse//自動翻轉
@property(nullable, copy) NSString *rotationMode;

CAKeyframeAnimation可以做很豐富的效果,下面展示了幾種純CAKeyframeAnimation做的效果:


CAKeyframeAnimation.gif

以上效果的代碼都比較簡單,量也比較大,這裏就不貼出來了,這裏可以下載:人口統計學關鍵幀動畫

CAAnimationGroup動畫組

CAAnimationGroup的屬性

//只有一個屬性,數組中接受CAAnimation元素
@property(nullable, copy) NSArray<CAAnimation *> *animations;
  • 可以看到CAAnimationGroup只有一個屬性一個CAAnimation數組。而且它繼承於CAAnimation,它具有CAAnimation的特性,所以它的用法和CAAnimation是一樣的,不同的是他可以包含ñ個動畫,也就是說他可以接受很多個CAAnimation並且可以讓它們一起開始,這就造成了動畫效果的疊加,效果就是ñ個動畫同時進行。

來看一個簡單的效果:


CAAnimationGroup.gif

這個是動畫是,旋轉,抖動,透明度一起作用在一起的效果,代碼在這裏人口統計學動畫組

CATransition轉場動畫

//轉場類型,字符串類型參數.系統提供了四中動畫形式:
//kCATransitionFade//逐漸消失
//kCATransitionMoveIn//移進來
//kCATransitionPush//推進來
//kCATransitionReveal//揭開
//另外,除了系統給的這幾種動畫效果,我們還可以使用系統私有的動畫效果:
//@"cube",//立方體翻轉效果
//@"oglFlip",//翻轉效果
//@"suckEffect",//收縮效果,動畫方向不可控
//@"rippleEffect",//水滴波紋效果,動畫方向不可控
//@"pageCurl",//向上翻頁效果
//@"pageUnCurl",//向下翻頁效果
//@"cameralIrisHollowOpen",//攝像頭打開效果,動畫方向不可控
//@"cameraIrisHollowClose",//攝像頭關閉效果,動畫方向不可控
@property(copy) NSString *type;
//轉場方向,系統一共提供四個方向:
//kCATransitionFromRight//從右開始
//kCATransitionFromLeft//從左開始
//kCATransitionFromTop//從上開始
//kCATransitionFromBottom//從下開始
@property(nullable, copy) NSString *subtype;
//開始進度,默認0.0.如果設置0.3,那麼動畫將從動畫的0.3的部分開始
@property float startProgress;
//結束進度,默認1.0.如果設置0.6,那麼動畫將從動畫的0.6部分以後就會結束
@property float endProgress;
//開始進度
@property(nullable, strong) id filter;

CATransition也是繼承CAAnimation,系統默認提供了12種動畫樣式,加上4個動畫方向,除了方向不可控的四種效果外,大概一共提供了36種動畫。

另外系統還給UIView的添加了很多分類方法可以快速完成一些簡單的動畫,如下:

的UIView(UIViewAnimation)

@interface UIView(UIViewAnimation)

+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;  // additional context info passed to will start/did stop selectors. begin/commit can be nested
//提交動畫
+ (void)commitAnimations;
//設置代理
+ (void)setAnimationDelegate:(nullable id)delegate;                          //設置動畫開始方法
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;                
//設置動畫結束方法
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;
//設置動畫時間:default = 0.2
+ (void)setAnimationDuration:(NSTimeInterval)duration;              
//設置動畫延遲開始時間:default = 0.0
+ (void)setAnimationDelay:(NSTimeInterval)delay;
//設置動畫延遲開始日期:default = now ([NSDate date])
+ (void)setAnimationStartDate:(NSDate *)startDate;                  
//設置動畫運動曲線:default =UIViewAnimationCurveEaseInOut
//UIViewAnimationCurveEaseInOut,//慢進慢出
//UIViewAnimationCurveEaseIn, //慢進快出
//UIViewAnimationCurveEaseOut,//快進慢出
//UIViewAnimationCurveLinear//勻速
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;              
//設置重複次數: default = 0.0.  May be fractional
+ (void)setAnimationRepeatCount:(float)repeatCount;
//設置是否翻轉動畫: default = NO. used if repeat 
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
//設置動畫是否從當前狀態開始:default = NO
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;
//設置動畫類型
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; 
//設置動畫是否有效
+ (void)setAnimationsEnabled:(BOOL)enabled;
//
+ (BOOL)areAnimationsEnabled;
//
+ (void)performWithoutAnimation:(void (^)(void))actionsWithoutAnimation
//
+ (NSTimeInterval)inheritedAnimationDuration 
@end

的UIView(UIViewAnimationWithBlocks)

@interface UIView(UIViewAnimationWithBlocks)
//以下方法都大同小異,就不一一做註釋了
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion 
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion;
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

@end

的UIView(UIViewKeyframeAnimations)

+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations

以上方法比較多,找值得說的簡單說一下吧:

//單視圖轉場動畫
+ (void)transitionWithView:(UIView *)view
                  duration:(NSTimeInterval)duration 
                   options:(UIViewAnimationOptions)options
                animations:(void (^ __nullable)(void))animations
                completion:(void (^ __nullable)(BOOL finished))completion
//雙視圖轉場動畫
+ (void)transitionFromView:(UIView *)fromView
                    toView:(UIView *)toView 
                  duration:(NSTimeInterval)duration 
                    options:(UIViewAnimationOptions)options
              completion:(void (^ __nullable)(BOOL finished))completion

這兩個都是轉場動畫,不同的是第一個是單視圖轉場,第二個是雙視圖轉場不過需要注意的是:單視圖轉場動畫只能用作屬性動畫做不到的轉場效果,比如屬性動畫不能給的UIImageView的形象賦值操作做動畫效果等。

我們可以看到以上兩個方法中都有一個共同的參數:
UIViewAnimationOptions

typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
    UIViewAnimationOptionLayoutSubviews            = 1 <<  0,
    UIViewAnimationOptionAllowUserInteraction      = 1 <<  1, // turn on user interaction while animating
    UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2, // start all views from current value, not initial value
    UIViewAnimationOptionRepeat                    = 1 <<  3, // repeat animation indefinitely
    UIViewAnimationOptionAutoreverse               = 1 <<  4, // if repeat, run animation back and forth
    UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5, // ignore nested duration
    UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6, // ignore nested curve
    UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7, // animate contents (applies to transitions only)
    UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8, // flip to/from hidden state instead of adding/removing
    UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9, // do not inherit any options or animation type

    UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // default
    UIViewAnimationOptionCurveEaseIn               = 1 << 16,
    UIViewAnimationOptionCurveEaseOut              = 2 << 16,
    UIViewAnimationOptionCurveLinear               = 3 << 16,

    UIViewAnimationOptionTransitionNone            = 0 << 20, // default
    UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20,
    UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20,
    UIViewAnimationOptionTransitionCurlUp          = 3 << 20,
    UIViewAnimationOptionTransitionCurlDown        = 4 << 20,
    UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20,
    UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20,
    UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20,
} NS_ENUM_AVAILABLE_IOS(4_0);

可以看到系統給到的是一個位移枚舉,這就意味着這個枚舉可以多個值同時使用,但是怎麼用呢?其實那些枚舉值可以分爲三個部分。
我們分別看一下每個枚舉的意思:
第一部分:動畫效果

UIViewAnimationOptionTransitionNone//沒有效果
UIViewAnimationOptionTransitionFlipFromLeft//從左水平翻轉
UIViewAnimationOptionTransitionFlipFromRight//從右水平翻轉
UIViewAnimationOptionTransitionCurlUp//翻書上掀
UIViewAnimationOptionTransitionCurlDown//翻書下蓋UIViewAnimationOptionTransitionCrossDissolve//融合
UIViewAnimationOptionTransitionFlipFromTop//從上垂直翻轉                    UIViewAnimationOptionTransitionFlipFromBottom//從下垂直翻轉

第二部分:動畫運動曲線

//開始慢,加速到中間,然後減慢到結束
UIViewAnimationOptionCurveEaseInOut
//開始慢,加速到結束
UIViewAnimationOptionCurveEaseIn
//開始快,減速到結束
UIViewAnimationOptionCurveEaseOut
//線性運動
UIViewAnimationOptionCurveLinear

第三部分:其他

//默認,跟父類作爲一個整體
UIViewAnimationOptionLayoutSubviews
//設置了這個,主線程可以接收點擊事件
UIViewAnimationOptionAllowUserInteraction
//從當前狀態開始動畫,父層動畫運動期間,開始子層動畫.
UIViewAnimationOptionBeginFromCurrentState
//重複執行動畫,從開始到結束, 結束後直接跳到開始態
UIViewAnimationOptionRepeat
//反向執行動畫,結束後會再從結束態->開始態
UIViewAnimationOptionAutoreverse
//忽略繼承自父層持續時間,使用自己持續時間(如果存在)
UIViewAnimationOptionOverrideInheritedDuration
//忽略繼承自父層的線性效果,使用自己的線性效果(如果存在)
UIViewAnimationOptionOverrideInheritedCurve
//允許同一個view的多個動畫同時進行     
UIViewAnimationOptionAllowAnimatedContent     
//視圖切換時直接隱藏舊視圖、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用於轉場動畫)             UIViewAnimationOptionShowHideTransitionViews
//不繼承父動畫設置或動畫類型.
UIViewAnimationOptionOverrideInheritedOptions

這下可以看到,這些枚舉功能都不一樣但是可以隨意組合,但是組合的時候需要注意,類型同一枚舉的一起不能使用比如UIViewAnimationOptionCurveEaseIn狀語從句:UIViewAnimationOptionCurveEaseOut

然後我們看一下轉場動畫的一些效果:

單視圖轉場


單視圖轉場.gif注意

雙視圖轉場


雙視圖轉場.gif注意

CATransition視圖轉場


CATransition.gif

動畫效果太多,GIF錄不了太大,效果沒有一一展示然後代碼再這裏:人口統計學轉場動畫

除了3D變換動畫,和繪圖相關的動畫,基本上我們常用到的動畫都在這裏了另外感謝這些參考博客的博主〜。
http://www.jianshu.com/p/ab0e7b291468
HTTP:// WWW .cocoachina.com / IOS / 20150105 / 10812.html
http://www.jianshu.com/p/240398d0609d
http://www.jianshu.com/p/c18588d4104a
http://www.jianshu.com/p/ 499a0689ec40
http://www.jianshu.com/p/a079a9bb20f9
http://www.jianshu.com/p/08fa17620dae
http://www.jianshu.com/p/90a7a1787d1b

原創內容,轉載請註明出處:

http://www.jianshu.com/p/3f48fabaca19



文/抱緊我的小鯉魚(簡書作者)
原文鏈接:HTTP://www.jianshu.com/p/3f48fabaca19
發佈了48 篇原創文章 · 獲贊 54 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章