最近在开发一个商城类app,需要一个加入购物车一个动画效果,自己写会很麻烦,我就在网上找了一些资料最后实现了想要的效果,这个实现主要就是iOS提供的动画库:CAAnimation
实现效果如下:
下面就是实现代码,只有一个类PurchaseCarAnimationTool
.h文件
typedef void (^animationFinisnBlock)(BOOL finish);
#define ScreenWidth [UIScreen mainScreen].bounds.size.width
#define ScreenHeight [UIScreen mainScreen].bounds.size.height
@interface PurchaseCarAnimationTool : NSObject
@property (strong , nonatomic) CALayer *layer;
@property (copy , nonatomic) animationFinisnBlock animationFinisnBlock;
/**
* 初始化
*
* @return <#return value description#>
*/
+ (instancetype)shareTool;
/**
* 开始动画
*
* @param view 添加动画的view
* @param rect view 的绝对frame
* @param finishPoint 下落的位置
* @param finishBlock 动画完成回调
*/
- (void)startAnimationandView:(UIView *)view
rect:(CGRect)rect
finisnPoint:(CGPoint)finishPoint
finishBlock:(animationFinisnBlock)completion;
/**
* 摇晃动画
*
* @param shakeView <#shakeView description#>
*/
+ (void)shakeAnimation:(UIView *)shakeView;
@end
下面是.m文件
#import "PurchaseCarAnimationTool.h"
@interface PurchaseCarAnimationTool()<CAAnimationDelegate>
@end
@implementation PurchaseCarAnimationTool
#pragma mark - instancetype
+ (instancetype)shareTool
{
return [[PurchaseCarAnimationTool alloc]init];
}
#pragma public function
- (void)startAnimationandView:(UIView *)view
rect:(CGRect)rect
finisnPoint:(CGPoint)finishPoint
finishBlock:(animationFinisnBlock)completion
{
//图层
_layer = [CALayer layer];
_layer.contents = view.layer.contents;
_layer.contentsGravity = kCAGravityResizeAspectFill;
rect.size.width = rect.size.width;
rect.size.height = rect.size.height; //重置图层尺寸
_layer.bounds = rect;
// _layer.cornerRadius = rect.size.width/2;
// _layer.masksToBounds = YES; //圆角
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
[keyWindow.layer addSublayer:_layer];
_layer.position = CGPointMake(rect.origin.x+view.frame.size.width/2, CGRectGetMidY(rect)); //a 点
/// 路径
[self createAnimationwithRect:rect finishPoint:finishPoint];
/// 回调
if (completion) {
_animationFinisnBlock = completion;
}
}
+ (void)shakeAnimation:(UIView *)shakeView
{
CABasicAnimation *shakeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
shakeAnimation.duration = 0.25f;
shakeAnimation.fromValue = [NSNumber numberWithFloat:-5];
shakeAnimation.toValue = [NSNumber numberWithFloat:5];
shakeAnimation.autoreverses = YES;
[shakeView.layer addAnimation:shakeAnimation forKey:nil];
}
#pragma mark - private function
/// 创建动画
- (void)createAnimationwithRect:(CGRect)rect
finishPoint:(CGPoint)finishPoint {
/// 路径动画
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:_layer.position];
[path addQuadCurveToPoint:finishPoint controlPoint:CGPointMake(ScreenWidth/2, rect.origin.y-80)];
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pathAnimation.path = path.CGPath;
/// 旋转动画
CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotateAnimation.removedOnCompletion = YES;
rotateAnimation.fromValue = [NSNumber numberWithFloat:0];
rotateAnimation.toValue = [NSNumber numberWithFloat:12];
rotateAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
/// 缩放动画
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.removedOnCompletion = YES;
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0]; // 开始时的倍率
scaleAnimation.toValue = [NSNumber numberWithFloat:0.25]; // 结束时的倍率
scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
/// 添加动画动画组合
CAAnimationGroup *groups = [CAAnimationGroup animation];
groups.animations = @[pathAnimation,rotateAnimation,scaleAnimation];
groups.duration = 1.0f;
groups.removedOnCompletion = NO;
groups.fillMode = kCAFillModeForwards;
groups.delegate = self;
[_layer addAnimation:groups forKey:@"group"];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
if (anim == [_layer animationForKey:@"group"]) {
[_layer removeFromSuperlayer];
_layer = nil;
if (_animationFinisnBlock) {
_animationFinisnBlock(YES);
}
}
}
@end
我是swift项目,这里使用是方式自然是swift语音风格。那么我们如何使用呢?
首先是加入购物车动画
let wCell = collectionView.cellForItem(at: indexPath)// 获取点击的第几个Cell
var rect = wCell?.frame
// 获取当前cell 相对于self.view 当前的坐标
rect!.origin.y = (rect?.origin.y)! - collectionView.contentOffset.y
var imageViewRect = imageView.frame
imageViewRect.origin.x = (rect?.origin.x)!
imageViewRect.origin.y = (rect?.origin.y)! + imageViewRect.origin.y
PurchaseCarAnimationTool.share()?.startAnimationandView(imageView, rect: imageViewRect, finisnPoint: CGPoint(x: kScreenWidth / 4 * 2.5, y: kScreenHeight - CGFloat(SafeAreaTopHeight)), finish: { (finish:Bool) in
if (self.tabBarController as AnyObject).isKind(of:MyTabBarController.classForCoder()) {
//此处就是另一个动画加入购物车抖动动画
PurchaseCarAnimationTool.shakeAnimation(self.tabBarController!.tabBar.subviews[3]);
}
})
以上便是整个动画的实现效果,希望对大家有所帮助