iOS snow animation

//
//  CTSnowAnimationView.h
//  CTMyCtrip
//
//  Created by alex on 16/1/4.
//  Copyright © 2016年 ctrip. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface CTSnowAnimationView : UIView
-(id)initWithFrame:(CGRect)frame;
-(void)startSnowWithFlakesNumber:(int)num duration:(float)duration;
-(void)stopSnowAnimation;
-(void)removeSnowAnimation;
@end
//
//  CTSnowAnimationView.m
//  CTMyCtrip
//
//  Created by alex on 16/1/4.
//  Copyright © 2016年 ctrip. All rights reserved.
//

#import "CTSnowAnimationView.h"

#define REPEATSNOW @"geneRepeatSnow"

@interface CTSnowAnimationView()
@property (strong, nonatomic) NSMutableArray<UIImageView*> *snowFlakes;
@end
@implementation CTSnowAnimationView

-(id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        return self;
    }
    return [[CTSnowAnimationView alloc] init];
}

-(void)removeSnowAnimation{
    for (UIView *flake in self.snowFlakes) {
        [flake removeFromSuperview];
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self name:REPEATSNOW object:nil];
    self.snowFlakes = nil;
}

-(void)startSnowWithFlakesNumber:(int)num duration:(float)duration{
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self.snowFlakes count] != num) {
            if ([self.snowFlakes count] != 0) {
                for (UIView *subview in self.snowFlakes) {
                    [subview removeFromSuperview];
                }
            }
            self.snowFlakes = [NSMutableArray array];
            for (int i = 0; i < num; i++) {
                UIImageView *tmpView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"myctrip_snowflake.png"]];
                tmpView.frame = CGRectZero;
                tmpView.userInteractionEnabled = FALSE;
                [self addSubview:tmpView];
                [self.snowFlakes addObject:tmpView];
            }
        }
        [self showFlakes:YES];
        
        [[NSNotificationCenter defaultCenter] removeObserver:self name:REPEATSNOW object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveRepeatNotification:) name:REPEATSNOW object:nil];
        for (UIView *flake in self.snowFlakes) {
            [flake.layer removeAllAnimations];
        }
        for (int i = 0; i < [self.snowFlakes count]; i++) {
            [self singleFlakeSnow:i withDuration:duration];
        }
    });
}

-(void)stopSnowAnimation{
    for (UIView *flake in self.snowFlakes) {
        [flake.layer removeAllAnimations];
    }
    [self showFlakes:false];
}


- (float)randomFloatBetween:(float)min and:(float)max {
    float diff = max - min;
    return (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + min;
}

-(void)showFlakes:(BOOL)need{
    for (UIImageView *flake in self.snowFlakes) {
        flake.hidden = !need;
    }
}

-(void)singleFlakeSnow:(int)index withDuration:(float)duration{
    UIView *flake = self.snowFlakes[index];
    int size = [self randomFloatBetween:8.0 and:14.0];
    CGRect flakeFrame = flake.frame;
    [flake.layer removeAllAnimations];
    flake.layer.opacity = 0.1;
    flakeFrame.origin.x = arc4random_uniform(CTScreenWidth);
    flakeFrame.origin.y = -size;
    flakeFrame.size.width = size;
    flakeFrame.size.height = size;
    flake.frame = flakeFrame;
    float delay = arc4random_uniform(5.0);
    [self layoutIfNeeded];
    [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseInOut animations:^{
        flake.frame = CGRectMake(flakeFrame.origin.x + 40 - arc4random_uniform(80), self.bounds.size.height, size, size);
        flake.layer.opacity = 1.0;
        [self layoutIfNeeded];
    } completion:^(BOOL finished) {
        if (finished) {
            [[NSNotificationCenter defaultCenter] postNotificationName:REPEATSNOW object:nil userInfo:@{@"index":[NSNumber numberWithInt:index],
                                                                                                        @"duration":[NSNumber numberWithFloat:duration]
                                                                                                        }];
        }
    }];
}

-(void)receiveRepeatNotification:(NSNotification *)notification{
    if ([[notification name] isEqualToString:REPEATSNOW]) {
        int index = [((NSNumber*)[notification.userInfo objectForKey:@"index"]) intValue];
        float duration = [((NSNumber*)[notification.userInfo objectForKey:@"duration"]) floatValue];
        [self singleFlakeSnow:index withDuration:duration];
    }
}


@end

Using AutoLayout:

 

 1 - (float)randomFloatBetween:(float)min and:(float)max {
 2     float diff = max - min;
 3     return (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + min;
 4 }
 5 
 6 -(void)showFlakes:(BOOL)need{
 7     for (UIImageView *flake in self.snowFlakes) {
 8         flake.hidden = !need;
 9     }
10 }
11 
12 -(void)singleFlakeSnow:(int)index{
13     UIView *flake = self.snowFlakes[index];
14     NSLayoutConstraint *x = self.flakesHorizonalPosition[index];
15     NSLayoutConstraint *y = self.flakesVerticalPosition[index];
16     int size = [self randomFloatBetween:8.0 and:14.0];
17     ((NSLayoutConstraint*)self.flakesWidth[index]).constant = size;
18     ((NSLayoutConstraint*)self.flakesHeight[index]).constant = size;
19     [flake.layer removeAllAnimations];
20     flake.layer.opacity = 0.1;
21     x.constant = arc4random_uniform(CTScreenWidth);
22     y.constant = -size;
23     float delay = arc4random_uniform(5.0);
24     [self layoutIfNeeded];
25     [UIView animateWithDuration:7.0 delay:delay options:UIViewAnimationOptionCurveEaseInOut animations:^{
26         x.constant = x.constant + 40 - arc4random_uniform(80);
27         y.constant = self.bounds.size.height;
28         flake.layer.opacity = 1.0;
29         [self layoutIfNeeded];
30     } completion:^(BOOL finished) {
31         if (finished) {
32             [[NSNotificationCenter defaultCenter] postNotificationName:REPEATSNOW object:nil userInfo:@{@"index":[NSNumber numberWithInt:index]}];
33         }
34     }];
35 }
36 
37 -(void)snowAnimation:(BOOL)need{
38     if (need ) {
39         dispatch_async(dispatch_get_main_queue(), ^{
40             [self showFlakes:YES];
41             self.snowGround.hidden = FALSE;
42             self.snowBackground.hidden = FALSE;
43             [[NSNotificationCenter defaultCenter] removeObserver:self name:REPEATSNOW object:nil];
44             [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveRepeatNotification:) name:REPEATSNOW object:nil];
45             for (UIView *flake in self.snowFlakes) {
46                 [flake.layer removeAllAnimations];
47             }
48             for (int i = 0; i < [self.snowFlakes count]; i++) {
49                 [self singleFlakeSnow:i];
50             }
51         });
52     }
53     else{
54         dispatch_async(dispatch_get_main_queue(), ^{
55             [[NSNotificationCenter defaultCenter] removeObserver:self name:REPEATSNOW object:nil];
56             for (UIView *flake in self.snowFlakes) {
57                 [flake.layer removeAllAnimations];
58             }
59             [self showFlakes:NO];
60         });
61     }
62 }
63 
64 -(void)receiveRepeatNotification:(NSNotification *)notification{
65     if ([[notification name] isEqualToString:REPEATSNOW]) {
66         int index = [((NSNumber*)[notification.userInfo objectForKey:@"index"]) intValue];
67         [self singleFlakeSnow:index];
68     }
69 }
View Code

 

posted on 2016-01-15 13:47  alex_wood  阅读(149)  评论(0编辑  收藏  举报