登录 立即注册
金钱:

Code4App-iOS开发-iOS 开源代码库-iOS代码实例搜索-iOS特效示例-iOS代码例子下载-Code4App.com

利用UIBezierPath实现加入购物车动画

[复制链接]
来自:  曦紫牧 分类: iOS精品源码 上传时间: 2018-4-5 16:30:45
Tag:

项目介绍:

2018-4-5.jpeg
GitHub地址
简书

前言 :

最近在重构公司的项目,在这个过程中发现很多简单的动画都零散的分部在VC或者View里面,不仅造成代码增多,还不容易管理,特别是购物车动画, 借着这个机会重新整理一下。

  • 坐标转换

  • UIBezierPath+ CAKeyframeAnimation关键帧动画

  • 利用坐标转换+关键帧动画实现一个购物车动画

1.坐标转换

- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;

字面的意思就是将视图A中的rect转换到B视图,返回在B视图对应的rect,在心董儿iOS convertRect熟悉吗?文中总结出这样一句话
“计算源上的被操作的对象相对于目标的frame”。 我们在开发中经常遇到根据某个特殊条件把A视图()的C视图(操作对象)添加到B视图(目标)(例如:点赞动画、加入购物车动画,查看头像大图),这个方法就派上用场了。
2018-04-03-5.26.54.png


怎么用坐标转换

我们先看一个简单的效果 ,将C视图移动到window中间,点击屏幕返回原来的位置.
5zye7SaEqT.gif
整个过程可以分解为三步.
第一步先获取C视图在window上的位置

  CGRect targetframe = [target.superview convertRect:target.frame toView:toView];
    target.frame = targetframe;

第二步将c视图移动到window的中间

  target.frame = CGRectMake((toView.frame.size.width-target.frame.size.width)*0.5, (toView.frame.size.height-target.frame.size.height)*0.5, target.frame.size.width, target.frame.size.height);

第三步获取C视图在A视图的位置,返回到原来的位置。

 CGRect targetframe = [m_pGrayView. superview convertRect:m_pGrayView.frame toView:m_pRedView];
  m_pGrayView.frame = targetframe;

#####2.UIBezierPath+ CAKeyframeAnimation
在不太会用UIBezierPath的时候,一直在想这个到底能干什么,在开发应用的过程中渐渐了解到了UIBezierPath可以做很多的事情,但是总的来说都是为某个目标提供路径。我个人用到的比较多有一下几点

  • 画圆角(不考虑离屏渲染)

  • 画虚线

  • 画路径结合CAKeyframeAnimation实现关键帧动画

画圆角(不考虑离屏渲染)

/* 
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect  byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
*/
    m_pRedView=[[UIView alloc] initWithFrame:CGRectMake(25, 120, 90, 90)];
    [m_pRedView setBackgroundColor:[UIColor redColor]];
    UIBezierPath *layerPath= [UIBezierPath bezierPathWithRoundedRect:m_pRedView.bounds byRoundingCorners: UIRectCornerAllCorners cornerRadii: CGSizeMake(5, 5)];
    CAShapeLayer *layer=[CAShapeLayer layer];
    layer.path =layerPath.CGPath;
    layer.frame = m_pRedView.bounds;
    m_pRedView.layer.mask =layer;

画虚线

/**
 @param pattern 画虚线的规格
 @param count 要画多少个这样的规格的虚线
 @param phase  离起始点偏移
- (void)setLineDash:(nullable const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase;
 */
  UIBezierPath *dashPath=[UIBezierPath bezierPathWithRect:CGRectMake(0,  (self.frame.size.height-8)*0.5, self.frame.size.width, 5)];
  CGFloat dash[] = {3.0, 1.0};
  dashPath.lineWidth = 0.5;
  [dashPath setLineDash:dash count:20 phase:3];
  [[UIColor blueColor] setFill];
  [dashPath stroke];

画路径结合CAKeyframeAnimation实现关键帧动画

     UIBezierPath *layerPath=[UIBezierPath bezierPathWithArcCenter:self.view.center radius:60 startAngle:-M_PI*0.5 endAngle:M_PI*1.5 clockwise:YES];
    layerPath.lineWidth = 3.5;
    CAShapeLayer  *shaperLayer=[CAShapeLayer layer];
    shaperLayer.frame = CGRectMake(self.view.frame.size.width*0.5-2.5, self.view.frame.size.height*0.5-60, 5.0, 5.0);
    shaperLayer.backgroundColor = [UIColor blueColor].CGColor;
    [self.view.layer addSublayer:shaperLayer];

    CAKeyframeAnimation * KeyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
    KeyframeAnimation.path =layerPath.CGPath;
    KeyframeAnimation.rotationMode =  kCAAnimationRotateAuto;
    KeyframeAnimation.calculationMode = kCAAnimationLinear;
    KeyframeAnimation.repeatCount = MAXFLOAT;
    KeyframeAnimation.duration  = 0.5;
    KeyframeAnimation.autoreverses =NO;
    [shaperLayer addAnimation:KeyframeAnimation forKey:@"KeyframeAnimation"];

3.利用坐标转换+关键帧动画实现一个购物车动画

我们首先看一下效果(录制的gif有点卡,在电脑上没有问题的)
cP2gDlWuoP.gif
我们可以看到整个流程大致上可以分为三个步骤,更详细的请到demo中查看。

    • 第一步利用坐标转换计算出fromPoint 和toPoint

    • 第二步根据第一步获取的坐标点画抛物线

      • 第三步CAKeyframeAnimation沿路径运动

    关键代码部分如下

    //layer
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(fromPoint.x-object.size.width*0.5, fromPoint.y-object.size.height*0.5, object.size.width, object.size.height);
        layer.contentsScale =[UIScreen mainScreen].scale;
        layer.contentsGravity = kCAGravityResizeAspectFill;
        layer.contents = (__bridge id _Nullable)(object.CGImage);
        
        //path
        UIBezierPath *movePath=[UIBezierPath bezierPath];
        [movePath moveToPoint:fromPoint];
        [movePath addQuadCurveToPoint:CGPointMake(toPoint.x-object.size.width*0.5, toPoint.y-object.size.height*0.5) controlPoint:CGPointMake(fromPoint.x-130, fromPoint.y-120)];
        
        CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
        keyframeAnimation.path =  movePath.CGPath;
        keyframeAnimation.rotationMode = kCAAnimationRotateAuto;
    
        CABasicAnimation  *rorationAnimation=[CABasicAnimation animationWithKeyPath:@"transfom.roration"];
        rorationAnimation.fromValue =@(0);
        rorationAnimation.toValue =@(M_PI*2);
        rorationAnimation.repeatCount = MAXFLOAT;
        rorationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.duration = duration;
        group.removedOnCompletion =NO;
        group.animations  =@[keyframeAnimation,rorationAnimation];
        group.duration =duration;
        group.fillMode=kCAFillModeForwards;
        [layer addAnimation:group forKey:@"group"];
        [inView.layer addSublayer:layer];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [layer removeFromSuperlayer];
            if (completion) {
                completion(YES);
            }
        });
    小结:
    • 在开发中要明确 操作 对象目标,分不清三者的关系,最后将导致UI布局错乱,还得从头开始。

    • 动画结束时要记得移除,CAAnimation的代理是强引用的,这个不小心就造成循环引用。

    相关源码推荐:

    我来说两句
    *滑动验证:
    所有评论(32)
    码农创新者 2018-4-8 10:47:58
    感谢分享,code4app有你更精彩
    回复
    乱世佳人520 2018-4-8 10:48:28
    mark,收藏了
    回复
    打个酱油的 2018-4-8 10:48:35
    膜拜大神~
    回复
    inta加加 2018-4-8 10:48:40
    支持,感谢,祝code4app越来越好~
    回复
    ff12345 2018-4-8 10:48:47
    相当不错,感谢无私分享精神!
    回复
    无限释囚 2018-4-8 10:49:11
    支持,感谢,祝code4app越来越好~
    回复
    code4app热心网友 2018-4-8 13:55:42
    正需要啊,感谢楼主无私分享!
    回复
    MrStar 2018-4-8 14:36:01
    楼主威武啊,Code4App有你更给力!
    回复
    code4app热心网友 2018-4-8 14:44:10
    强烈支持楼主ing……
    回复
    1234下一页
    提取码:  下载次数:63 状态:已购或VIP 售价:0(原价:15)金钱 下载权限:初级码农 
    2978 0 63
    联系我们
    首页/微信公众账号投稿

    帖子代码编辑/版权问题

    QQ:435399051,742864542

    如何获得代码达人称号?

    代码贡献英雄榜
    用户名 下载数
    通过邮件订阅最新 Code4App 信息
    上一条 /4 下一条
    联系我们
    关闭
    合作电话:
    13802416937
    Email:
    435399051@qq.com
    商务市场合作/投稿
    问题反馈及帮助
    联系我们

    广告投放| 广东互联网违法和不良信息举报中心|中国互联网举报中心|Github|申请友链|手机版|Code4App ( 粤ICP备15117877号-1 )

    快速回复 返回顶部 返回列表