1. 程式人生 > >iOS幾種動畫效果的實現

iOS幾種動畫效果的實現

做過一個專案,裡面涉及到的動畫效果比較多,在這裡做個小小的總結。

直線動畫效果

實現一個物體在某段時間從一個點移動到另一個點。
效果如下:
這裡寫圖片描述
動畫相關程式碼如下:
動畫模型:

@interface AnimationModel : NSObject

@property(nonatomic,strong) NSArray * images;
@property(nonatomic,assign) float fromX;
@property(nonatomic,assign) float fromY;
@property(nonatomic,assign) float toX;
@property
(nonatomic,assign) float toY; @property(nonatomic,assign) BOOL loop; @property(nonatomic,assign) float time; @end

動畫實現:

-(void)addSingleLineAnimationToView:(UIView *)view animationModel:(AnimationModel *)model{
    CABasicAnimation* moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"
]; moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(model.fromX,model.fromY)]; moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(model.toX,model.toY)]; moveAnimation.duration = model.time; moveAnimation.removedOnCompletion = NO; moveAnimation.repeatCount
= MAXFLOAT; if (model.loop == 0) { moveAnimation.repeatCount = 1; } [view.layer addAnimation:moveAnimation forKey:@"singleLineAnimation"]; }

爆炸點贊動畫效果

效果有點像撒花,效果如下:
這裡寫圖片描述
這個效果的實現也是我在網上找到的,封裝了一個View和一個button,呼叫很方便,下面我貼一下呼叫的程式碼,後面會給出完整程式碼的地址。
呼叫程式碼:

-(BZFireworkAnimationButton *)praiseButton{
    if (!_praiseButton) {
        _praiseButton = [[BZFireworkAnimationButton alloc] initWithFrame:CGRectMake(150, 200, 50, 50)];
        _praiseButton.particleImage = [UIImage imageNamed:@"button_bulletin_board_collected"];
        _praiseButton.particleScale = 0.05f;
        _praiseButton.particleScaleRange = 0.02f;
        [_praiseButton addTarget:self action:@selector(praiseAction:) forControlEvents:UIControlEventTouchUpInside];
        [_praiseButton setImage:[UIImage imageNamed:@"button_bulletin_board_uncollect"] forState:UIControlStateNormal];
        [_praiseButton setImage:[UIImage imageNamed:@"button_bulletin_board_collected"] forState:UIControlStateSelected];
    }
    return _praiseButton;
}

-(void)praiseAction:(BZFireworkAnimationButton *)button{
    if (button.selected) {
        [button popInsideWithDuration:0.4f];
    }else{
        [button popOutsideWithDuration:0.4];
        [button animate];
    }
    button.selected = !button.selected;
}

心跳(放大縮小)動畫效果

效果如下:
這裡寫圖片描述
實現程式碼:

-(void)setupHeartbeatAnimationInView:(UIView *)view{
    // 設定為縮放
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    // 動畫選項設定
    animation.duration = 1.2; // 動畫持續時間
    animation.repeatCount = 10000000000; // 重複次數
    animation.autoreverses = YES; // 動畫結束時執行逆動畫
    // 縮放倍數
    animation.fromValue = [NSNumber numberWithFloat:1.0]; // 開始時的倍率
    animation.toValue = [NSNumber numberWithFloat:1.4]; // 結束時的倍率
    animation.removedOnCompletion = NO;
    // 新增動畫
    [view .layer addAnimation:animation forKey:@"scale-layer"];
}

上下浮動效果

效果如下:
這裡寫圖片描述
程式碼實現如下:

@interface FloatViewController ()

//判斷是否是當前ViewController,如果不是,則停止動畫,否則動畫一直在,且dealloc方法不會被呼叫
@property(nonatomic,assign) BOOL isCurrentVC;
@end

@implementation FloatViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor orangeColor];

    UIImageView * animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(30, 105, 144, 350)];
    animationImageView.image = [UIImage imageNamed:@"image_city_angel_login_girl"];
    [self setAnimationImageViewAnimation:animationImageView];
    [self.view addSubview:animationImageView];
}

-(void)dealloc{
    NSLog(@"FloatViewController dealloc");
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.isCurrentVC = YES;
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    self.isCurrentVC = NO;
}

-(void)setAnimationImageViewAnimation:(UIImageView *)animationImageView{
    [UIView animateWithDuration:1 animations:^{
        animationImageView.frame = CGRectMake(30, 90, 144, 350);
    }];
    [UIView animateWithDuration:1 delay:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        animationImageView.frame = CGRectMake(30, 105, 144,350);

    } completion:^(BOOL finished) {
        if (self.isCurrentVC) {
            [self setAnimationImageViewAnimation:animationImageView];
        }
    }];

}

這個動畫效果有一點需要注意的就是需要手動停止,最好離開該頁面的時候就手動讓它停止,否則會造成記憶體洩漏。如果是push到下級頁面,手動停止了動畫,回到該頁面時還需要動畫啟動的話,可以給動畫的view一個tag值,然後在viewWillAppear中呼叫一下setAnimationImageViewAnimation方法。

圖片序列gif效果

開發中經常遇到動圖的效果,如果美術給的是gif圖,那麼可以使用SDWebImage中的方法進行播放,如果給的是圖片序列,我們可以用UIImageView自帶的屬性來實現。
效果如下:
這裡寫圖片描述
使用UIImageView自帶屬性實現程式碼如下:

NSArray * images = @[@"gif_ferriswheel1",@"gif_ferriswheel2",@"gif_ferriswheel3",@"gif_ferriswheel4",@"gif_ferriswheel5",@"gif_ferriswheel6"];
    UIImageView * imageViews = [[UIImageView alloc] init];
    UIImage * image = [UIImage imageNamed:images[0]];
    imageViews.frame = CGRectMake(120, 200, image.size.width, image.size.height);
    NSMutableArray * imagesArray = [NSMutableArray array];
    for (NSString * imagesName in images) {
        UIImage * tempImage = [UIImage imageNamed:imagesName];
        [imagesArray addObject:tempImage];
    }
    imageViews.animationImages = [imagesArray copy];
    imageViews.animationDuration = 0.9;
    imageViews.animationRepeatCount = 1000000000;
    [imageViews startAnimating];
    [self.view addSubview:imageViews];

這種方式需要注意的是animationImages這個數組裡面的物件是UIImage,所以千萬不要把圖片名稱的陣列直接賦值,會造成崩潰。

直線+Gif效果

圖片既有位移的改變,又在改變位移的同時自身在變,比如一個人走路。
效果如圖:
這裡寫圖片描述
實現動畫主要程式碼如下:

-(void)initData{
    NSString * jsonPath = [[NSBundle mainBundle] pathForResource:@"animation" ofType:@"json"];
    NSData * data = [NSData dataWithContentsOfFile:jsonPath];
    NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    NSArray * lineGifArray = dic[@"walk_animation"];
    self.lineGifArray = [NSMutableArray array];
    for (NSDictionary * item in lineGifArray) {
        AnimationModel * model = [[AnimationModel alloc] init];
        [model setValuesForKeysWithDictionary:item];
        [self.lineGifArray addObject:model];
    }
}

-(void)setupLineGifAnimation{
    for (AnimationModel * model in self.lineGifArray) {
        UIImageView * animationImageView = [[UIImageView alloc] init];
        animationImageView.image = [UIImage imageNamed:model.images[0]];
        animationImageView.frame = CGRectMake(model.toX, model.toY, animationImageView.image.size.width, animationImageView.image.size.height);
        NSMutableArray * imagesArray = [NSMutableArray array];
        for (NSString * imagesName in model.images) {
            UIImage * tempImage = [UIImage imageNamed:imagesName];
            [imagesArray addObject:tempImage];
        }
        animationImageView.animationImages = [imagesArray copy];
        animationImageView.animationDuration = 1.2;
        animationImageView.animationRepeatCount = 1000000000;
        [animationImageView startAnimating];
        [self.view addSubview:animationImageView];
        [self addSingleLineAnimationToView:animationImageView animationModel:model];
    }
}

-(void)addSingleLineAnimationToView:(UIView *)view animationModel:(AnimationModel *)model{
    CABasicAnimation* moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    moveAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(model.fromX,model.fromY)];
    moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(model.toX,model.toY)];
    moveAnimation.duration = model.time;
    moveAnimation.removedOnCompletion = NO;
    moveAnimation.repeatCount = MAXFLOAT;
    if (model.loop == 0) {
        moveAnimation.repeatCount = 1;
    }
    [view.layer addAnimation:moveAnimation forKey:@"lineGifAnimation"];
}

這個動畫效果涉及到兩個時間,一個位移從起點到終點的時間和一個完成一套動作的時間,這兩個時間需要去調才能做出最自然的效果,我這裡提供的是思路,兩個時間沒有花時間去調,請見諒~

動畫能讓我們的app顯得更有生機和活力,也還有很多其他的動畫效果,記住的話更好,記不住可以抽時間整理一下,下次再寫的時候找起來方便。
這六個動畫效果我自己寫了一個完整的demo,點選這裡或者這裡獲取程式碼。