前言
碰到个需求,做一个金币入袋的动画,如下图这种效果,因为用的地方比较多,所以我把它进行了封装,使用起来比较方便,加入购物车和这个实现思路一致,大家可以试试。
思路
拿到后的想法是用粒子动画,参考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