引言
效果:https://live.csdn.net/v/embed/167358
demo下载地址:https://download.csdn.net/download/u011018979/20045082
视频:http://mpvideo.qpic.cn/0bf2tqaecaaa2qalghgsavqfbhgdigoaaqia.f10002.mp4?
应用场景:购物车模块,将商品添加商品到购物车
如果是扫商品条码添加购物车,推荐延迟1.5S再重新识别。
代码语言:javascript复制
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf reStartDevice];
});
I、demo下载
从CSDN下载Demo:https://download.csdn.net/download/u011018979/20045082
1、应用场景:购物车模块,将商品添加商品到购物车 2、文章地址:https://blog.csdn.net/z929118967/article/details/103660899 3、视频地址:https://live.csdn.net/v/167358
II 、代码实现
添加商品到购物车的事件传递,由cell->V->VC 核心处理代码在工具类JoinCartAnimationTool中
2.1 商品的cell
BillingRightCell.m
- 添加商品按钮的动画处理
[self.counterV.animationSubject subscribeNext:^(UIButton *btn) {
@strongify(self);
if (btn) {
if ([self.delegate respondsToSelector:@selector(performAnimationWithCell:buttonView:)]) {
[self.delegate performAnimationWithCell:self buttonView:self.iconImgV];
}
}
}];
2.2 开(下)单界面
BillingView
- 处理动画事件
#pragma mark - BillingRightCellDelegate
- (void)performAnimationWithCell:(BillingRightCell *)cell
buttonView:(UIImageView *)view
{
// CGRect parentRect = [cell convertRect:view.frame toView:self];
if (self.joinCartAnimationWithViewblock) {
self.joinCartAnimationWithViewblock(view);
}
}
2.3 下单商品的控制器VC
展示商品数据的VC:BillingViewController
- 处理动画
[_vcView setJoinCartAnimationWithViewblock:^(id _Nonnull sender) {
//sender 即添加按钮的控件
//btn.imageView:展示购物车icon的imageView
//weakSelf.view:当前控制器的视图
[[weakSelf AnimationTool] joinCartAnimationWithView:sender toView:weakSelf.topButtonView.shoppingBtn.btn.imageView inView:weakSelf.view];
}];
- 处理动画的工具类属性
@property (strong, nonatomic) JoinCartAnimationTool *AnimationTool;
- (JoinCartAnimationTool *)AnimationTool{
if (nil == _AnimationTool) {
QCTJoinCartAnimationTool *tmpView = [[JoinCartAnimationTool alloc]init];
_AnimationTool = tmpView;
}
return _AnimationTool;
}
2.4 动画处理工具类 JoinCartAnimationTool
.h
代码语言:javascript复制/**
@param imageView 移动的View: 例如商品图片
@param boxImgV view移动的最后目标视图: 例如购物车icon控件
@param inView imageView boxImgV 参考的坐标系。例如购物车VC的View
*/
-(void)joinCartAnimationWithView:(UIImageView *)imageView toView:(UIView*)boxImgV inView:(UIView*)inView;
.m
代码语言:javascript复制#import "JoinCartAnimationTool.h"
@interface JoinCartAnimationTool ()
/**
用于动画
*/
@property (strong, nonatomic) UIBezierPath *path;
@property (assign, nonatomic) CGFloat animationDuration;
@property (strong, nonatomic) CALayer *dotLayer;
//self.topButtonView.shoppingBtn.btn.imageView
@property (strong, nonatomic) UIView *endView;
@end
@implementation JoinCartAnimationTool
- (instancetype)init
{
self = [super init];
if (self) {
self.animationDuration = 0.5f;
}
return self;
}
#pragma mark - ******** joinCartAnimationWithRect
/**
以inView为参考,计算开始位置和结束位置的rect
@param imageView 移动的View: 例如商品图片
@param boxImgV view移动的最后目标视图: 例如购物车icon控件
@param inView imageView boxImgV 参考的坐标系。例如购物车VC的View
*/
-(void)joinCartAnimationWithView:(UIImageView *)imageView toView:(UIView*)boxImgV inView:(UIView*)inView
{
self.endView = boxImgV;
CGRect rect = [imageView.superview convertRect:imageView.frame toView:inView];
CGRect endRect = [boxImgV.superview convertRect:boxImgV.frame toView:inView];
CGPoint endPoint = CGPointMake(endRect.origin.x endRect.size.width/2, endRect.origin.y endRect.size.height/2);
CGFloat startX = rect.origin.x rect.size.width/2;
CGFloat startY = rect.origin.y rect.size.height/2;
_path= [UIBezierPath bezierPath];
[_path moveToPoint:CGPointMake(startX, startY)];
[_path addLineToPoint:CGPointMake(endPoint.x, endPoint.y)];
// [_path addCurveToPoint:CGPointMake(endPoint.x, endPoint.y)
// controlPoint1:CGPointMake(startX, startY)
// controlPoint2:CGPointMake(startX - 180, startY - 200)];
_dotLayer = [CALayer layer];
// _dotLayer.backgroundColor = [UIColor purpleColor].CGColor;
NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject:imageView];
UIImageView *copyImgV = [NSKeyedUnarchiver unarchiveObjectWithData:tempArchive];
UIImage *image = [self circleImage:copyImgV];
_dotLayer.contents = (__bridge id)image.CGImage;
_dotLayer.frame = imageView.frame;
[inView.layer addSublayer:_dotLayer];
[self groupAnimation];
}
-(UIImage *)circleImage:(UIImageView *)imageView{
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 0);
[[UIBezierPath bezierPathWithOvalInRect:imageView.bounds] addClip];
[imageView drawRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageView.image;
}
-(void)groupAnimation
{
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.path = _path.CGPath;
animation.rotationMode = kCAAnimationLinear;
CABasicAnimation *alphaAnimation1 = [CABasicAnimation animationWithKeyPath:@"bounds"];
alphaAnimation1.duration = 0.1;
alphaAnimation1.repeatCount = 1;
alphaAnimation1.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, _dotLayer.bounds.size.width*1.5, _dotLayer.bounds.size.height*1.5)];
alphaAnimation1.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, _dotLayer.bounds.size.width, _dotLayer.bounds.size.height)];
alphaAnimation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[_dotLayer addAnimation:alphaAnimation1 forKey:@"bounds"];
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
alphaAnimation.duration = self.animationDuration;
alphaAnimation.fromValue = [NSNumber numberWithFloat:1.0];
alphaAnimation.toValue = [NSNumber numberWithFloat:0.1];
alphaAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
CAAnimationGroup *groups = [CAAnimationGroup animation];
groups.animations = @[animation,alphaAnimation];
groups.duration = self.animationDuration;
groups.removedOnCompletion = NO;
groups.fillMode = kCAFillModeForwards;
groups.delegate = self;
// [groups setValue:@"groupsAnimation" forKey:@"animationName"];
[_dotLayer addAnimation:alphaAnimation forKey:@"cornerRadius"];
[_dotLayer addAnimation:groups forKey:nil];
[self performSelector:@selector(removeFromLayer:) withObject:_dotLayer afterDelay:self.animationDuration];
// WS(weakSelf);
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.animationDuration/2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [weakSelf playingBoxAnimation];
// });
}
- (void)removeFromLayer:(CALayer *)layerAnimation{
[layerAnimation removeFromSuperlayer];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStart:(CAAnimation *)anim{
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
// 完成可以使用比例动画scale
UIView *endView = self.endView;
CABasicAnimation *alphaAnimation1 = [CABasicAnimation animationWithKeyPath:@"bounds"];
alphaAnimation1.duration = 0.1;
alphaAnimation1.repeatCount = 1;
alphaAnimation1.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, endView.bounds.size.width*1.5, endView.bounds.size.height*1.5)];
alphaAnimation1.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, endView.bounds.size.width, endView.bounds.size.height)];
alphaAnimation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[endView.layer addAnimation:alphaAnimation1 forKey:@"bounds"];
}
@end
see also
iOS Document Scanner:矩形边缘识别(边缘检测 ) CIDetectorTypeRectangle
https://kunnan.blog.csdn.net/article/details/117367345