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

2018-4-5.jpeg

前言 :

最近在重构公司的项目,在这个过程中发现很多简单的动画都零散的分部在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);
        }
    });

GitHub地址

小结:
  • 在开发中要明确 操作 对象目标,分不清三者的关系,最后将导致UI布局错乱,还得从头开始。
  • 动画结束时要记得移除,CAAnimation的代理是强引用的,这个不小心就造成循环引用。
参考部分

iOS convertRect熟悉吗?
iOS绘图出现的错误

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,321评论 6 30
  • 先看看CAAnimation动画的继承结构 CAAnimation{ CAPropertyAnimation { ...
    时间不会倒着走阅读 1,562评论 0 1
  • 雨意绵绵似无休, 早醒赖床闻敲窗, 常约晨来健身起, 不爱淋雨爱抱被。
    风轻云淡蓝熙阅读 135评论 1 0
  • 亲爱的雨涵: 今天妈妈说了好几次,要做一个好人、正直的人,要有一颗善良的心。虽然你老嫌妈妈长篇大论,但因为这事太重...
    方怡阅读 99评论 0 0
  • 奶奶成长日记4 奶奶又进步了! 每天早上奶奶都要叫放放吃饭的,即使放放每次都会因此发躁!今天奶奶...
    未来的美好1111111阅读 195评论 1 0