原型从网上找的,动效使用了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; } //  最后一个球向左push
UIPushBehavior *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的更多相关文章

  1. H5动效的常见制作手法

    众所周知,一个元素,动往往比静更吸引眼球: 一套操作界面,合适的动态交互反馈能给用户带来更好的操作体验: 一个H5运营宣传页,炫酷的动画特效定能助力传播和品牌打造. 近两年,小到loading动画,表 ...

  2. Android 实例子源代码文件下载地址380个合集

      android 城市列表特效 - 触摸查找源码 .rar: http://www.t00y.com/file/64337887 android 日记系统源码(数据库的基本操作) .rar: htt ...

  3. Art-Directing SVG图像viewBox属性

    Art-Directing SVG图像viewBox属性 作者:彦子 日期:2015-06-02 点击:992 svg 译者注:根据Google Dev文档的解释,Art Direction在这篇文章 ...

  4. App启动页设计实例与技巧

    App启动页,也称闪屏页,最初是为缓解用户等待Web/iOS/Android App数据加载的焦虑情绪而出现,后被设计师巧妙用于品牌文化展示,服务特色介绍以及功能界面熟悉等平台进行设计,被赋予了更加丰 ...

  5. [libGDX游戏开发教程]使用libGDX进行游戏开发(12)-Action动画

    前文章节列表:  使用libGDX进行游戏开发(11)-高级编程技巧   使用libGDX进行游戏开发(10)-音乐音效不求人,程序员也可以DIY   使用libGDX进行游戏开发(9)-场景过渡   ...

  6. jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、

    脚 本 之 家 www.jb51.net 脚本云 专题 素材下载 电子书 软件下载 源码下载 服务器常用软件 a5交易 首页 网页制作 脚本专栏 脚本下载 网络编程 数据库 CMS教程 电子书籍 平面 ...

  7. HTML5 动画效果的多种实现方式

    HTML5 动画效果的多种实现方式 1.  CSS3 transform + transition https://www.w3.org/TR/css-transforms-1/ https://ww ...

  8. 在Winform界面菜单中实现动态增加【最近使用的文件】菜单项

    在我们一些和文件处理打交道的系统中,我们往往需要记录下最近使用的文件,这样方便用户快速打开之前浏览或者编辑过的文件,这种在很多软件上很常见,本文主要介绍在Winform界面菜单中实现[最近使用的文件] ...

  9. 微信禁用右上角的分享按钮,WeixinJSBridge API以及隐藏分享的子按钮等菜单项

    <!--禁用微信分享按钮--> <script> function onBridgeReady() { WeixinJSBridge.call('hideOptionMenu' ...

随机推荐

  1. android 获取IMEI号

    android 获取 imei号码 核心代码: Imei = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getDeviceId( ...

  2. 命令行创建Windows窗体应用程序

    csc:(C Sharp Compiler) 类似于 javac (java Compiler) 命令行的编译工具 位置:C:\Windows\Microsoft.NET\Framework\v4.0 ...

  3. Spring(3.2.3) - Beans(1): Spring 容器

    BeanFactory & ApplicationContext org.springframework.beans.factory.BeanFactory 是最基本的 Spring 容器接口 ...

  4. MyBatis(3.2.3) - Dynamic SQL

    Sometimes, static SQL queries may not be sufficient for application requirements. We may have to bui ...

  5. response小结(三)—输出随机图片(验证码功能实现)

    本文是一个很简单的向网页上输出验证码的实现喲!通过注释解释清楚了每一步! Myeclipse下的Package Explorer显示文件结构如下: ResponseDemo.java实现了输出随机图片 ...

  6. 【网络收集】Sql Server datetime 常用日期格式转换

    ) , sfrq, ) 我们经常出于某种目的需要使用各种各样的日期格式,当然我们可以使用字符串操作来构造各种日期格式,但是有现成的函数为什么不用呢? SQL Server中文版的默认的日期字段date ...

  7. css Hack 以及css的一些兼容问题小结

    坚持每天做总结.今天下班还算早.写个跟css兼容有关的知识点.便于后期查看与学习.一.先说说各种主流浏览器的内核 浏览器最重要或者说核心的部分是“Rendering Engine”,可大概译为“渲染引 ...

  8. javascript笔记——闭包

    花了三天时间,终于弄清楚闭包的各种写法和注意的事项,以及以前写,经常出错的地方,特此做一个总结,虽然不够专业,但是对于那些初学者来说,绝对对闭包的理解事半功倍. 案例一: function aa(){ ...

  9. linux同步

    1. 内核同步 主要是防止多核处理器同时访问修改某段代码,或者在对设备驱动程序进行临界区的保护. 1 .互斥量 头文件 #include<linux/mutex.h> 初始化方法: 静态初 ...

  10. Windows系统 环境变量

    用户变量与系统变量 用户变量只对当前用户有效,而系统变量对所有用户有效.在检索命令时,系统变量会排在用户变量的前面.也就是说,如果两个地方都包含同一个命令,则优先执行系统变量指示路径下的命令. set ...