首页 > 代码库 > 滚珠菜单动效-b

滚珠菜单动效-b

原型从网上找的,动效使用了CAAnimation和UIDynamic物理引擎。  gitHub  :https://github.com/BearRan/FlowMenuAnimation

大致步骤如下:

  • 把效果图截取一张,拖到Sketch做背景

  • 新建图层,使用钢笔工具临摹背景图勾勒出路径

  • 注意:勾勒时可以选择非镜像的控制点,这样方便调整曲线

     

 


接着点击Sketch右下角的倒出按钮,格式选为SVG格式

 


将生成的SVG文件拖入到codePaint中,拖入成功后会直接看到如下界面

 

看到代码路径后可以整段copy出来,当然,我建议把所有的点抽离出来,方便做适配

 

代码绘制凹槽动画

demo的AppDelegate.h中有以下这些开关,可以自己调配,方便观察

 


单个滚珠动效演示,这样看应该比较容易理解。其实我是盖了一个新的图层专门用来做滚珠动效的。

控制点就是用普通的UIAniamtion实现的,在动画之行的过程中,通过CADisplayLink实时观察Point的PresentLayer的position来不停的重绘贝塞尔曲线。


2.滚珠动画该分解成几个步骤

主要分为以下步骤
阶段一:滚珠一起滚落下来时到最高点的阶段;
阶段二:滚珠滚落到最高点后回流的的阶段;
阶段三:滚珠消失阶段;

3.如何分解滚珠的物理效果

UIDynamic有以下物理效果

  • UIGravityBehavior:重力行为

  • UICollisionBehavior:碰撞行为

  • UISnapBehavior:捕捉行为

  • UIPushBehavior:推动行为

  • UIAttachmentBehavior:附着行为

  • UIDynamicItemBehavior:动力元素行为


UIGravityBehavior:重力行为

 
#pragma mark  重力行为- (UIGravityBehavior *)addGravityBehavior:(id <UIDynamicItem>)item{    UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] init];    [gravityBehavior addItem:item];    [_animator addBehavior:gravityBehavior];    return gravityBehavior;}




UICollisionBehavior:碰撞行为

适用于:UIView和父类view的边界碰撞,以及和其他UIView碰撞
这里可以配合重力行为来设定小球的运动路径

  

 

 

#pragma mark  碰撞行为- (UICollisionBehavior *)addCollisionBehavior:(id <UIDynamicItem>)item{    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] init];    [collisionBehavior addItem:item];    [collisionBehavior addBoundaryWithIdentifier:@"path" forPath:_beizerPath];    [_animator addBehavior:collisionBehavior];    return collisionBehavior;}

UISnapBehavior:捕捉行为

顾名思义,不解释

UIPushBehavior:推动行为
使用瞬间或持续的力并按照某一方向作用于某个UIView
用于开始或结束时的小球推动

 
#pragma mark  显现动画,第一个球向右的推力- (UIPushBehavior *)addPushBehavior_inFirstBtn{    UIButton *tempBtn = _btnArray[0];    UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[tempBtn] mode:UIPushBehaviorModeInstantaneous];    pushBehavior.pushDirection = CGVectorMake(1, 0.3);    pushBehavior.magnitude = 1.6;    [_animator addBehavior:pushBehavior];    return pushBehavior;}
 

UIAttachmentBehavior:附着行为

UIView和某个UIView的相互吸附行为
此处用于小球见的相互吸附作用

 
#pragma mark  添加球与球之间的附着行为- (UIAttachmentBehavior *)addAttachmentBehavior_item:(id <UIDynamicItem>)item attachToItem:(id <UIDynamicItem>)attachToItem{    SpecialBtn *tempBtn = (SpecialBtn *)item;    UIAttachmentBehavior *attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToItem:attachToItem];    [attachmentBehavior setLength:tempBtn.width + 20];    [attachmentBehavior setDamping:10.01];    [attachmentBehavior setFrequency:1];    [_animator addBehavior:attachmentBehavior];    return attachmentBehavior;}
 

UIDynamicItemBehavior:动力元素行为

一些其他的物理元素,比如摩擦力,线速度阻力,角速度阻力等

 
#pragma mark  动力元素行为- (UIDynamicItemBehavior *)addDynamicItemBehavior:(id <UIDynamicItem>)item{    UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[item]];    itemBehavior.resistance = 0;    itemBehavior.allowsRotation = YES;    itemBehavior.angularResistance = 4.0;    itemBehavior.friction = 0.8;    [_animator addBehavior:itemBehavior];    return itemBehavior;}

 

 

阶段一:滚珠一起滚落下来时到最高点的阶段球与球之间的附着行为 + 重力行为+碰撞行为+ 动力元素行为+ 第一个球向右的推力#pragma mark 显现动画

 
#pragma mark 显现动画- (void)showBtnsAnimation{    _animatorStatus = kAnimatorStatus_open;    [_animator removeAllBehaviors];    if (showPath) {        _pathLayer.path = _beizerPath.CGPath;        _pathLayer.fillColor = [UIColor clearColor].CGColor;        _pathLayer.strokeColor = [UIColor orangeColor].CGColor;        _pathLayer.lineWidth = 2.0;        [self.layer addSublayer:_pathLayer];    }    CGFloat btn_gap = [self setXX:16];    for (int i = 0; i < [_btnArray count]; i++) {        SpecialBtn *tempBtn = _btnArray[i];        tempBtn.tag = i;        [self addSubview:tempBtn];        //  设定初始位置        [tempBtn setX:(tempBtn.width + btn_gap) * ([_btnArray count] - 1 - i) + btn_gap];        [tempBtn setY:-tempBtn.height];        //  添加球与球之间的附着行为        if (i > 0) {            [self addAttachmentBehavior_item:_btnArray[i] attachToItem:_btnArray[i - 1]];        }        //  重力行为        UIGravityBehavior *gravityBehavior = [self addGravityBehavior:tempBtn];        if (i == [_btnArray count] - 1) {            //  最后一个球处理重力行为            [self dealLastBtnGravityBehavior:gravityBehavior tempBtn:tempBtn];        }        //  碰撞行为        [self addCollisionBehavior:tempBtn];        //  动力元素行为        UIDynamicItemBehavior *itemBehavior = [self addDynamicItemBehavior:tempBtn];        if (i == [_btnArray count] - 1) {            //  最后一个球增加密度,以防止出现的时候,由于惯性的原因导致飞起来            itemBehavior.density = 1.8;        }    }    //  第一个球向右的推力    [self addPushBehavior_inFirstBtn];}

阶段二:滚珠滚落到最高点后回流的的阶段球与球之间的附着行为 + 重力行为+碰撞行为+ 动力元素行为+ 最后一个球向左pushf

 
 
for (int i = 0; i < [_btnArray count]; i++) {    //  添加球与球之间的附着行为    if (i > 0) {                    UIAttachmentBehavior *attachmentBehavior = [self addAttachmentBehavior_item:_btnArray[i] attachToItem:_btnArray[i - 1]];         [attachmentBehavior setFrequency:5];         [attachmentBehavior setLength:tempBtn.width + 5];     }     //  重力行为     [self addGravityBehavior:_btnArray[i]];      //  碰撞行为     [self addCollisionBehavior:_btnArray[i]];      //  动力元素行为     UIDynamicItemBehavior *itemBehavior = [self addDynamicItemBehavior:_btnArray[i]];     itemBehavior.angularResistance = 15.0;} //  最后一个球向左pushUIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[tempBtn] mode:UIPushBehaviorModeContinuous];pushBehavior.pushDirection = CGVectorMake(-1, -0.5);pushBehavior.magnitude = 2.3; [_animator addBehavior:pushBehavior];
  

阶段三:滚珠消失阶段球与球之间的附着行为 + 重力行为+碰撞行为+ 动力元素行为+ 最后一个球向左push(和阶段二几本一致,只是推动的力大了一些)

 
 
#pragma mark 消退动画- (void)closeBtnsAniamtion{
   NSLog(@"-- closeBtnsAniamtion");    _animatorStatus = kAnimatorStatus_close;    SpecialBtn *lastBtn = (SpecialBtn *)[_btnArray lastObject];    [_animator removeAllBehaviors];    for (int i = 0; i < [_btnArray count]; i++) {        //  添加球与球之间的附着行为        if (i > 0) {            UIAttachmentBehavior *attachmentBehavior = [self addAttachmentBehavior_item:_btnArray[i] attachToItem:_btnArray[i - 1]];            [attachmentBehavior setFrequency:5];            [attachmentBehavior setLength:lastBtn.width + 5];        }        //  重力行为        UIGravityBehavior *gravityBehavior = [self addGravityBehavior:_btnArray[i]];        if (i == 0) {            [self dealFirstDisappearBtnGravityBehavior:gravityBehavior tempBtn:_btnArray[i]];        }        //  碰撞行为        [self addCollisionBehavior:_btnArray[i]];        //  动力元素行为        [self addDynamicItemBehavior:_btnArray[i]];    }    //  最后一个球向左push    UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[lastBtn] mode:UIPushBehaviorModeContinuous];    pushBehavior.pushDirection = CGVectorMake(-1, -0.5);    pushBehavior.magnitude = 10.0;    [_animator addBehavior:pushBehavior];}
 
  

demo地址:

作者:熊熊xr

原文地址:http://code4app.com/forum.php?mod=viewthread&tid=9264&extra=page%3D62%26filter%3Dsortid%26orderby%3Ddateline%26sortid%3D1

滚珠菜单动效-b