前言

某天我接到了UI发给我的两张图:

需求图.png

看到图的时候我一脸懵逼,显然我需要做一个页面切换的指示动画。老实说,从大三暑假开始做iOS开发也一年有余了,但是遇到复杂动画总是唯恐避之不及,只做过一些简单的位移动画。大脑中的舒适区总是让我下意识避开麻烦的问题选择简单的解决方式。UI很善解人意得告诉我,你可以先用图片替代动画,以后有空慢慢完善。我突然不知哪里来的底气拍了拍胸脯:“没问题,包在我身上”。装出去的b泼出去的水,没办法,我只好下定决心趁此机会好好钻研一下形变动画。(就在写这篇文章的时候,UI看到了我最终的成果并点赞,顿时成就感爆棚)。

最终成果如图:

demo.gif
具体代码详见:https://github.com/lfny2580832/NYTubeAnimation

需求分析

打定主意要搞定这个动画,我首先在脑海中一遍遍模拟了整体效果。想象这是一个封闭光滑的管道,管道两端是两个可伸缩变形的白块,当点击下一步滑动到第二个页面时,管道左边的白块被一股向右的力推动,逐步压缩进管道中,最后从右边释放出来。这种感觉很抽象,只能隐隐约约想象出大概的效果。我在纸上一遍遍得模拟每一个细节,开始进行简化和分解。

简化

如果只看设计图,显然中间管道过窄,白块无法通过。于是我尝试着将中间管道变宽,并用keynote利用圆弧与矩形画出了简化图:

需求简化图.png

思路是不是立即清晰很多!实际上简化的过程我花了很长时间。一开始我并没有用圆形,而是用贝塞尔曲线来拟合图形,但是在拟合过程后中遇到了重重困难。比如要根据角度来确定某段弧线中贝塞尔点的控制点的长度(一小段曲线中至少需要计算五个点的坐标,计算非常复杂,且拟合效果不是很好),以及多个贝塞尔曲线UIBeizerPath闭合时各种错位等等问题。多次尝试无果后,我退而求其次,使用了UIBeizerPath 自带圆弧方法来构造整体图形以及动画。这段时间我花了整整两天。

简化图画出来之后,心中有了思路,即用UIBeizerPath拟合图形构造CAShapeLayer,然后使用CADisplayLink完成帧动画。对CAShapeLayer和CADisplayLink做动画不太熟悉的同学可以参考我之前的一个水波动画,github地址:https://github.com/lfny2580832/NYWaterWave

waterwave.gif

分解

看着上面的简化图,我又懵逼了。这丫该怎么动起来?而且要想让效果看起来自然流畅,在形状开始压缩和在管道中移动速度肯定是不一样的,由管道的狭窄程度决定,要计算的话难度太大,于是我便手动指定这两块区域的速度(所有参数都可以在代码中指定)。经过简单的分解后我画出了如下的参考图,并标注了参数:

整体分解图.png

看着上图脑海里有了些思路。我不可能只用一个CAShapelayer就做完这一系列的动画,当然只能将其分解成各个部分,分别进行动画。想象每个部分在整个动画中的位置及大小,当每个部分都做好之后,再完美拼接起来,整个动画不就完成了吗?

实现

属性与实例变量

下图属性与实例变量位置及命名只是个人习惯,方便开发时自己查看,其中所有点都是根据上面的参考图来命名的,大家可以对照查看:

变量.png

看起来一脸懵逼?没关系,我会将每个分解出来的模块完整动画向大家展示出来。由于代码有点多有点复杂,就直接以图片形式像大家展示。这其中大部分都只是很多简单的动画,但将他们组合起来就不一样啦!

速度控制点—dynamic_Q_d和dynamic_Q2_d

这两个点来控制在不同阶段的速度,只需改变自增量即可,逻辑稍稍复杂。

dynamic_Q_d.png

dynamic_Q2_d.png

左边的圆弧— leftSemiShape

leftSemiShape.gif

leftSemiShape.png

主体矩形区域—maintubeShape

mainTubeShape.gif

mainTubeShape.png

火山形状—volcanoShape

volcanoShape.gif

火山形状也是整个动画中最复杂的一部分,需要一些简单的计算,下面附上计算使用的参考图:

火山形状参考图.png

我们可以根据Q点移动的距离(dynamic_Q2_d)计算出b夹角,再通过UIBeizerPath画出相应的形状:

volcanoShape.png

白块右方圆形—rightCircleShape

rightCircleShape.gif

rightCircleShape.png

尾部圆形形状—tailCircleShape

tailCircleShape.gif

tailCircleShape.png

管道形状—tubeShape

tubeShape.gif

tubeShape.png

背景形状—wholeShape

wholeShape.png

背景形状只需要将上方所有图形拼合起来并扩大一圈即可,在此就不附代码了。

拼合

整体效果.gif

总结

当动画效果做出来后,再将其封装起来,开始事件、完成委托都变得那么简单。写这篇文章记录我的思考过程是想让更多人敢于挑战自己,其实很多东西并没有那么难,认真下去就能完成。如果总是待在自己的舒适区,很难提高自己的水平。主动挑战自己,将一个复杂的问题分解成一个个小目标,然后一一达成,问题就迎刃而解啦!

文/牛严(简书作者)
原文链接:http://www.jianshu.com/p/8a569dfd1c4b
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

iOS开发之——从零开始完成页面切换形变动画的更多相关文章

  1. iOS开发UI篇—transframe属性(形变)

    iOS开发UI篇—transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移.缩放比例和旋转角度 常用的创建transform结构体方法分两 ...

  2. iOS开发:使用Tab Bar切换视图

    iOS开发:使用Tab Bar切换视图 上一篇文章提到了多视图程序中各个视图之间的切换,用的Tool Bar,说白了还是根据触发事件使用代码改变Root View Controller中的Conten ...

  3. IOS开发中UIBarButtonItem上按钮切换或隐藏实现案例

    IOS开发中UIBarButtonItem上按钮切换或隐藏案例实现案例是本文要介绍的内容,这个代码例子的背景是:导航条右侧有个 edit button,左侧是 back button 和 add bu ...

  4. iOS开发UI篇—transframe属性(形变)

    iOS开发UI篇—transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移.缩放比例和旋转角度 常用的创建transform结构体方法分两 ...

  5. iOS开发CoreAnimation解读之一——初识CoreAnimation核心动画编程

    iOS开发CoreAnimation解读之一——初识CoreAnimation核心动画编程 一.引言 二.初识CoreAnimation 三.锚点对几何属性的影响 四.Layer与View之间的关系 ...

  6. iOS开发之微信聊天页面实现

    在上篇博客(iOS开发之微信聊天工具栏的封装)中对微信聊天页面下方的工具栏进行了封装,本篇博客中就使用之前封装的工具栏来进行聊天页面的编写.在聊天页面中主要用到了TableView的知识,还有如何在俩 ...

  7. iOS开发之虾米音乐频道选择切换效果分析与实现

    今天博客的内容比较简单,就是看一下虾米音乐首页中频道选择的一个动画效果的实现.之前用mask写过另外一种Tab切换的一种效果,网易云音乐里边的一种Tab切换效果,详情请移步于"视错觉:从一个 ...

  8. iOS开发——代码生成TabBar与视图切换具体解释

    我在之前多篇博客中解说了在不使用storyboard而使用nib文件的情况下.使用代码生成导航栏并进行跳转,具体能够參考<iOS开发--界面跳转与返回及视图类型具体解释><iOS纯代 ...

  9. iOS开发基础知识:Core Animation(核心动画)

    Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就可以实现非常强大的功能. Core A ...

随机推荐

  1. @SuppressWarnings—注解用法详解

    一.前言 编码时我们总会发现如下变量未被使用的警告提示: 上述代码编译通过且可以运行,但每行前面的“感叹号”就严重阻碍了我们判断该行是否设置的断点了.这时我们可以在方法前添加 @SuppressWar ...

  2. [SAP ABAP开发技术总结]RETURN、STOP、EXIT、CHECK、LEAVE、REJECT

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  3. POJ 1979 Red and Black (红与黑)

    POJ 1979 Red and Black (红与黑) Time Limit: 1000MS    Memory Limit: 30000K Description 题目描述 There is a ...

  4. eclipse svn异常:RA layer request failed 的解决方案

    这几天svn总是出问题,网上搜了好多资料,今天才真正找到解决办法. RA layer request failedsvn: OPTIONS of 'https://192.168.0.104/svn/ ...

  5. Codeforces Round #376 (Div. 2) F. Video Cards 数学,前缀和

    F. Video Cards time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  6. 利用JDK的中Proxy动态代理实现Spring的AOP技术

    首先给出设计模式静态代理与动态代理的学习: http://layznet.iteye.com/blog/1182924   讲的不错 然后我们实现AOP 就要求我们对委托的所有方法的调用实现拦截 代理 ...

  7. namespace使用总结

    1.防止引用文件中函数名相同,导致函数重定义错误: //test1.php <?php namespace foo; function func(){ echo "test1/func ...

  8. Android Netty框架的使用

    Netty框架的使用 1 TCP开发范例 发送地址---192.168.31.241 发送端口号---9223 发送数据 { "userid":"mm910@mbk.co ...

  9. white-space: nowrap

    CSS:需要加上宽度(width:100px).超出隐藏(overflow:hidden;).强制在同一行显示(white-space: nowrap;).省略号(text-overflow:elli ...

  10. JS获取用户控件中的子控件Id

    用户控件 <asp:HiddenField ID="hfGradeId" runat="server" /> <asp:HiddenField ...