iOS 金币入袋(收金币)动画

前言

碰到个需求,做一个金币入袋的动画,如下图这种效果,因为用的地方比较多,所以我把它进行了封装,使用起来比较方便,加入购物车和这个实现思路一致,大家可以试试。

未命名.gif

思路

拿到后的想法是用粒子动画,参考iOS CAEmitterLayer粒子动画详解,但是后来又觉得不对,因为粒子动画没办法决定动画的终点,所以我觉得这里应该是路径动画实现。

路径动画实现起来还算是比较简单,根据起点终点设置好路径,然后这么多个image用延时的方法逐个生成,最后执行动画即可,动画结束后将创建的image移除掉,这就是总体思路了。
下面看代码。

代码

//.h文件
#import <UIKit/UIKit.h>
@class ShootButtonSetting;

@interface HHShootButton : UIButton

@property (nonatomic, strong) ShootButtonSetting *setting;

- (instancetype)initWithFrame:(CGRect)frame andEndPoint:(CGPoint)point;
@end

typedef NS_OPTIONS(NSUInteger, ShootButtonAnimationType) {
    ShootButtonAnimationTypeLine       = 0,  //直线
    ShootButtonAnimationTypeCurve      = 1,  //曲线
};
//默认设置
@interface ShootButtonSetting : NSObject

@property (nonatomic, assign) int totalCount;//动画产生imagView的个数,默认10个
@property (nonatomic, assign) CGFloat timeSpace; //产生imageView的时间间隔,默认0.1
@property (nonatomic, assign) CGFloat duration;//动画时长, 默认1s
@property (nonatomic, strong) UIImage *iconImage; //图片,默认为button自身图片
@property (nonatomic, assign) ShootButtonAnimationType animationType;//动画类型,默认曲线
// Factory method to help build a default setting
+ (ShootButtonSetting *)defaultSetting;
@end
//.m文件
#import "HHShootButton.h"
@interface HHShootButton()<CAAnimationDelegate>
@property (nonatomic, strong) NSMutableArray *coinTagArray;
@property (nonatomic, assign) CGPoint point;
@end

@implementation HHShootButton

- (instancetype)initWithFrame:(CGRect)frame andEndPoint:(CGPoint)point{
    if (self = [super initWithFrame:frame]){
        _coinTagArray = [[NSMutableArray alloc] init];
        self.setting = [ShootButtonSetting defaultSetting];
        //目的地的位置
        self.point = CGPointMake(point.x - frame.origin.x, point.y - frame.origin.y);
        [self addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return self;
}

- (void)buttonAction{
    for(int i = 0; i < self.setting.totalCount; i ++){
        //延时 注意时间要乘i 这样才会生成一串,要不然就是拥挤在一起的
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(i*self.setting.timeSpace * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self initCoinViewWithInt:i];
        });
    }
}

- (void)initCoinViewWithInt:(int)i{

    UIImageView *imageView = [[UIImageView alloc] initWithImage:self.setting.iconImage ?: self.imageView.image];
    //设置中心位置
    imageView.center = CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0);
    //初始化金币的位置
    imageView.tag = i + 1000; //设置tag时尽量设置大点的数值
    //将tag添加到数组,用于判断移除
    [self.coinTagArray addObject:[NSNumber numberWithInt:(int)imageView.tag]];
    [self addSubview:imageView];
    [self setAnimationWithLayer:imageView];
}

- (void)setAnimationWithLayer:(UIView *)imageView{

    UIBezierPath *movePath = [UIBezierPath bezierPath];
    [movePath moveToPoint:CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0)];

    switch (self.setting.animationType) {
        case ShootButtonAnimationTypeLine://直线
            [movePath addLineToPoint:self.point];
            break;
        case ShootButtonAnimationTypeCurve://曲线
            //抛物线
            [movePath addQuadCurveToPoint:self.point controlPoint:CGPointMake(self.point.x, self.center.y)];
            break;
        default:
            break;
    }

    //位移动画
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    //移动路径
    animation.path = movePath.CGPath;
    animation.duration = self.setting.duration;
    animation.autoreverses = NO;
    animation.repeatCount = 1;
    animation.calculationMode = kCAAnimationPaced;
    animation.delegate = self;
    [imageView.layer addAnimation:animation forKey:@"position"];
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    if (flag){//动画执行结束移除view
        NSLog(@"动画结束");
        UIView *coinView =(UIView *)[self viewWithTag:[[self.coinTagArray firstObject] intValue]];
        [coinView removeFromSuperview];
        [self.coinTagArray removeObjectAtIndex:0];
    }
}

@end

#pragma mark - Setting Methods
@implementation ShootButtonSetting

+ (ShootButtonSetting *)defaultSetting{
    ShootButtonSetting *defaultSetting = [[ShootButtonSetting alloc] init];
    defaultSetting.totalCount = 10;
    defaultSetting.timeSpace = 0.1;
    defaultSetting.duration = 1;
    defaultSetting.animationType = ShootButtonAnimationTypeCurve;
    return defaultSetting;
}
@end

代码中都有很好的注释,这是我封装起来的,具体使用时导入头文件然后像初始化按钮一样初始化,传入目的地的位置,如果没有设置image则默认是按钮的图片,demo中提供了两种,一种是默认button图片,一种是设置了图片。

HHShootButton *shootBtn = [[HHShootButton alloc] initWithFrame:CGRectMake(10, 300, 80, 80) andEndPoint:self.iconImageView.center];
    [shootBtn setImage:[UIImage imageNamed:@"icon_xin"] forState:UIControlStateNormal];
    shootBtn.setting.animationType = ShootButtonAnimationTypeLine;
    [self.view addSubview:shootBtn];

其实,加入购物车的动画和这个大同小异,购物车动画只用生成一个UIImageView,然后加上图片旋转动画即可。
demo地址HHShootButtonDemo,打开它运行即可,希望大家喜欢,记得star✨哦!

参考

http://code1.okbase.net/codefile/ParabolaViewController.m_2014082227116_5.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值