前言

某天我接到了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. java web开发必备知识

    从各种招聘网站的要求上筛选出了一些java开发的一些基本的要求,对照自身看看有哪些缺陷. java基础 既然是java web开发,java SE肯定要学好了. 多线程,IO,集合等,对队列,缓存,消 ...

  2. CUBRID学习笔记 19 sql语句1

    创建 欢迎转载 ,转载时请保留作者信息.本文版权归本人所有,如有任何问题,请与我联系wang2650@sohu.com . 过错 create table tableName (字段名 字段类型 pr ...

  3. EditPlus添加到右键菜单

    1.Alt+R 键打开“运行” 2.“运行”中输入:regedit 打开注册表    (1.在 "我的电脑HKEY_CLASSES_ROOT*" 下新建项 shell: (2.在 ...

  4. .NET/C# 使用Stopwatch测量运行时间

    Stopwatch类:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.stopwatch(v=vs.100).aspx 常用属性和 ...

  5. Android 数据库升级解决方案

    转自:http://blog.csdn.net/leehong2005/article/details/9128501 请考虑如下情况: 在数据库升级时,不同版本的数据库,他们定义的表结构完全可能是不 ...

  6. datagrid实现行的上移和下移

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  7. 工作流学习——Activiti整体认识二步曲 (zhuan)

    http://blog.csdn.net/zwk626542417/article/details/46594505 ***************************************** ...

  8. 转!!Java JTable 根据表格内容 自动调整表格列宽

    //根据表格内容 自动调整列宽http://blog.sina.com.cn/s/blog_5e54d6140100s1d3.html

  9. javascript的语句和函数

    1.for-in语句:是一种精准的迭代语句,可以用来枚举对象的属性. 2.label语句:在代码中添加标签,以便将来使用,由break和continue语句调用. 3.with语句:将代码的作用域设置 ...

  10. linux 重命名文件和文件夹

    linux下重命名文件或文件夹的命令mv既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a目录移动到/b下,并重命名为c mv /a /b/c 其实在文本模式 ...