关闭

动画分析步骤“三步曲”

标签: iOS动画iOSiOS实例iOS动画核心技术
572人阅读 评论(0) 收藏 举报
分类:

摘要: 本文将实现简单的“登录界面按钮移动效果”,并通过此动画效果介绍动画设计和分析的思路。本文不仅旨在让大家弄清动画效果是如何通过代码来实现的,更重要的是希望大家通过对本文的学习,掌握动画设计和分析的思路。本文选自《iOS动画——核心技术与案例实战》

  首先先来看看动画设计中的三个角色:产品设计师、算法分析师以及伟大的程序员都有哪些职责。
(1)产品设计师:告诉大家想做一个什么样的动画。
(2)算法分析师:分析动画的实现原理并设计相应的动画算法。
(3)程序员:思考如何用代码实现算法。
  在一般中小规模的公司中,开发人员往往都是身兼数职。不仅要编写代码还要参与到算法的设计中去,甚至参与到动画原型的设计中去。所以弄清楚动画设计过程中的不同角色,以及搞清楚动画的分析过程是非常有必要的。

1 动画分析方法

  下图是我们想要实现的动画效果,那么如何来分析它呢?其实产品设计师在设计动画时,如果能够将动画分解为单帧图像,或者能够较为慢速地展现动画的变化过程,那么对于算法分析师和程序员分析动画的原理,以及设计合适的展现算法起着非常重要的作用。下图描述了登录按钮从左到右逐渐移动的效果,并最后停留在视图层中间位置这一过程。
【图1】

  这个动画效果非常简单,可以用一句话来描述其实现算法,即图像的水平方向位置坐标和时间呈线性渐变关系。接下来思考如何用代码实现这个效果。按照动画的展示过程,这里将动画分为:动画起始阶段、动画进行阶段和动画结束阶段。

1.动画起始阶段

  在动画启动的瞬间,希望动画从屏幕可视界面外飞入进来。如下图所示的登录按钮是需要实现的动画起始位置。
【图2】
  在iOS视图中,左上角为视图的原点(0,0),水平向右为x轴递增方向,竖直向下为y轴递增方向,只有当View视图位于手机屏幕展示坐标系之内,大家才能看到(虚线区域内控件不可见),否则登录按钮是不可见的。所以在动画的起始阶段可以将动画的位置属性设置在界面之外。

2.动画进行阶段

  经过前面的分析,大家已经了解了这个动画效果的实现算法,即登录按钮的坐标沿水平方向随时间线性变化。如表1.1所示描述了不同时间段登录按钮的坐标变化情况。幸运的是大家不需要手动设计这一过程,甚至不需要手动写线性渐变的方法,因为iOS在UIView的显示层已经帮我们把这个功能集成了。iOS在UIView图层中不仅集成了动画的线性渐变方法,而且动画的加速、减速以及复杂的动画变化时间函数、运动路径函数也已经为大家集成好了,所以只需要学会如何使用这些丰富的API即可,且这个功能只需要几行代码就可以实现。
  表1.1 6S下QQ图标移动效果:QQ图标x、y坐标随时间变化关系表
图片描述

3.动画结束阶段

  在动画效果结束之后没有触发新的回调事件,只是更新了当前登录按钮的最后位置,所以图片最终停留在视图层的中间位置。

2 登录按钮移动动画效果:闭包形式

首先创建一个单视图工程,创建好之后可以看到下图的工程文件目录结构:
【图3】
  动画实现的第一阶段:动画起始阶段
  在开始正式添加动画代码之前需要为应用添加一个背景图片。在Main.storyboard中为整个工程添加一个已经准备好的背景图片,背景图片依托在UIImageView上。
【图4】
  上图为当前工程的Main.storyboard中图层结构,其中View Controller为整个工程的视图控制器,login为UIImageView登录背景图片。下图示是准备好的背景图片,通过下图可以看出,要想实现最初所示的动画效果,只需为整个登录界面添加一个登录按钮即可。
【图5】
  动画起始阶段代码需要放在什么位置才合适呢?要想弄清楚这个问题先搞清楚ViewController.swift 中几个方法的执行顺序。需要关注以下3个方法。

viewDidLoad()
viewWillAppear()
viewDidAppear()

  在应用启动之后,在viewDidLoad中会装载所有的View视图,注意,虽然所有View视图都被装载进来,但是这时所有的View视图并不是可见的。程序接着调用viewWillAppear方法,这是视图在展现之前需要调用的方法。而最后调用viewDidAppear,表明所有的视图已经可见。经过以上分析,大家应该清楚,在动画起始阶段可以将所有的初始化代码放置在viewDidLoad()方法中。具体实现代码如下所示。

1   var loginButton:UIButton?
2   override func viewDidLoad() {
3       super.viewDidLoad()
4       loginButton = UIButton(frame: CGRect(x:-394,y:230,
                      width:self.view.frame.width-20*2,height:50))
5      loginButton!.backgroundColor = UIColor(red: 50/255.0, green: 185/255.0, blue: 170/255.0, alpha: 1.0)
6       loginButton!.setTitle("登录", for: UIControlState. normal)
7      self.view.addSubview(loginButton!)
    }

  代码第1行创建了一个UIButton登录按钮。第3行重写viewDidLoad方法,表明应用启动之后首先通过调用viewDidload方法加载各种UI组键。第4行设置当前UIButton登录按钮的位置,按钮的x坐标设置在整个界面之外,因此当前Button按钮是不可见的。第5行为登录按钮添加一个淡绿色背景。第6行设置登录按钮Title内容。最后一行将按钮添加到self.view图层上。
  动画实现的第二阶段和第三阶段:动画进行阶段和动画结束阶段
要想实现应用打开动画即展现的效果,需要在View视图整体展现之前完成动画实现的第二阶段和第三阶段的设置(因为如果视图已经显示了才设置动画效果,那么会有动画不连贯的现象),所以这部分功能只能放置在viewWillAppear方法中。
这里使用的UIButton按钮和UI控件都是继承UIView类,UIView类中有一个动画方法可以完成我们想要实现的功能:

open class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Swift.Void)

  该方法属于类方法,类名可以直接调用,表明为当前的UIView添加一个动画效果,它的每个参数的含义如下。

  • duration:表明动画执行周期。
  • animations:表明动画执行内容。

注意,这里animations是一个闭包,使用闭包的方式将动画代码追加进去。在闭包中只需要将动画的结束状态设置完成,那么动画从开始到结束的中间过程,iOS都会自动实现。下面为viewWillAppear()中的动画实现代码。

    override func viewWillAppear(_ animated: Bool) {
        UIView.animate(withDuration: 1, animations: {
          self.loginButton!.frame = CGRect(x:20,
                y:self.loginButton!.frame.origin.y, 
                 width:self.loginButton!.frame.width, 
                 height:self.loginButton!.frame.height))
        })
    }

  animate方法中,duration表明动画执行周期为1s,动画闭包部分表明登录按钮最终的位置,即最终停留在手机屏幕的中间位置。

3 登录按钮移动动画效果:方法形式

  除了使用闭包的方法之外,还可以使用另外一种方式实现这个动画效果,即通过commit相关方法的形式来实现。通过修改viewWillAppear()中的内容,可以实现相同的动画效果。下面是动画移动效果的另外一种代码实现方式。

    override func viewWillAppear(animated: Bool) {
1        UIView.beginAnimations(nil, context: nil)//动画开始
2        UIView.setAnimationDuration(1)//动画周期设置
3        loginButton!.frame = CGRect(x:20,
               y:loginButton!.frame.origin.y,
               width:loginButton!.frame.width,
               height:loginButton!.frame.height)//动画位置设置
4       UIView.commitAnimations()//动画提交
    }

  代码第1行表明动画开始,这里先忽略需要传递的参数,可以先传递两个nil。第2行设置动画执行周期,这里将动画周期设置为1s。第3行将登录按钮设置在屏幕中间位置。代码最后一行将动画效果提交到系统上运行。
  其实无论是第2节的动画实现方法抑或是第3节的动画实现方法,都可以把动画实现的过程总结为下面的3个步骤。
【图6】
  而第2节和第3节实现动画的唯一区别就是一个使用闭包的形式,而另一个使用beginAnimations和commitAnimations方法的形式启动动画。

4 UIView视图中常见动画的属性分析

  我们在第2节和第3节主要依靠UIView下的frame属性来实现登录按钮从左到右的进入效果。那么UIView下的其他属性是不是也可以有类似的效果呢?要想回答这个问题,首先需要弄清楚UIView都有哪些常见的属性。

1.位置属性:frame bounds center

  frame、bounds、center都是描述UIView的位置信息,不同的是frame可以对x坐标、y坐标、width、height四个属性进行操作,frame的x坐标和y坐标相对于父控件的原点来计算,而bounds一般只能对width、height进行操作,它的x、y坐标只相对于自身而言,center描述的是x、y信息,即UIView的中心位置。下面是CGRect、origin、size的代码描述。

public struct CGRect {
    public var origin: CGPoint
    public var size: CGSize
    public init()
    public init(origin: CGPoint, size: CGSize)
}

  再来看看三者的数据类型。frame是CGRect类型,它是一个结构体,在结构体中包含origin和size两个属性。其中origin描述UIView的x、y坐标起始位置信息,size描述UIView的width、height宽高信息。我们再来看看origin的CGPoint和size的CGSize又是什么。

  CGpoint中包含了UIView的x、y坐标,而CGSize中包含了UIView的Width、Height信息。通过对frame中数据类型的追本溯源,可以得到以下结论:CGRect分别对应x坐标、y坐标、width、height四个属性。这四个属性表明当前UI在它的父控件上的位置,如self.view上。
  通过以上分析可以知道,可以通过x、y坐标修改UIView的移动位置,还可以通过修改width或者height来修改UIView的拉伸、收缩效果。对于bounds属性使用最多的还是width、height属性,center则经常使用x、y坐标属性。

2.透明度属性:alpha(透明度属性、范围0-1、浮点型)

  UIView的alpha透明度属性也可以用作动画效果。当alpha为0时,表明UIView已经隐藏,当alpha为1时UIView显示。结合这一特征可以通过修改alpha在动画开始、结束时的值,实现UIView的淡入淡出效果。

3.Layer属性:圆角渐变、边框颜色、阴影、3D等高级动画效果

  UIView是视图显示的容器,负责内容显示和事件响应。每个UIView都有一个Layer图层,在这个图层中承载的是视图的内容,所以结合Layer可以实现很多高级的动画效果。当然除了这些之外,UIView还有很多其他属性,在后面的章节中会为大家一一呈现。

5 小结

  通过对本文的学习,相信大家基本上掌握了动画分析的基本步骤,在这里总结一下动画实现的三个步骤:
(1)设置视图的动画初始状态。
(2)添加视图的动画相应属性。
(3)设置视图的动画最终状态。
  在通过帧分解等方法了解了动画的实现原理之后,通过这三个步骤可以很方便地实现各种动画效果。本章结合登录按钮移动效果为大家展示了动画分析和实现的全过程,并通过代码详细介绍了通过闭包方式,以及beginAnimations和commitAnimations方法的形式实现动画。
  对于UIView中常见的动画属性,结合UIView对视图的位置、透明度、几何形状给大家做了简要的分析,在后面的章节中会结合具体的代码,为大家呈现缤纷多彩的动画效果。
  本文选自《iOS动画——核心技术与案例实战》,点此链接可在博文视点官网查看。
                      图片描述
  想及时获得更多精彩文章,可在微信中搜索“博文视点”或者扫描下方二维码并关注。
                       图片描述

0
0
查看评论

若每一条指令都可以分解为取指、分析和执行三步。已知取指时间t取指=5△t,分析时间t分析=2△t,执行时间t执行=5△t。如果按顺序方式从头到尾执行完500条指令需___(4)___ △t。

2005年下半年软件设计师上午试题<br /> <br />若每一条指令都可以分解为取指、分析和执行三步。已知取指时间t取指=5△t,分析时间t分析=2△t,执行时间t执行=5△t。如果按顺序方式从头到尾执行完500条指令需___(4)___ △t。如果按照[执行]...
  • qingfengke78
  • qingfengke78
  • 2010-09-15 00:58
  • 7003

Direct初始化三步曲

 Direct初始化三步曲 一.初始化1.IDirect3D9,IDirect3D9几个定义   typedef struct IDirect3D9 *LPDIRECT3D9, *PDIRECT3D9;用途:此接口主要是IDirect3DDevice9创建的前...
  • dingdingko
  • dingdingko
  • 2009-11-06 10:26
  • 971

身份管理三步曲

如今,身份认证已经成为开启电子商务的一把钥匙。在网络这个虚拟世界中,每一笔交易都会涉及不同身份的人:员工、企业合作伙伴和客户,因此,有效的身份管理就成了其中必不可少的一环。作为一种多层面、多角度的安全保障,身份管理解决方案已经成为信息技术的一项重大任务。掌握用户的准确信息有助于帮助降低成本,以及实现...
  • linsan2008
  • linsan2008
  • 2007-02-13 15:48
  • 647

程序员英语学习三步曲

作为一名程序员,可以说每天都要和英语打交道,特别是浏览一些国外的技术网站的时候,许多人就感觉英语水平跟不上了,那么,程序员怎么学英语?现在请看程序员英语学习三步曲。 一、读文档不能只读代码 读文档只读代码,是很多程序员的习惯,也是导致程序员虽然读了很多英文资料,英文水平却没有相应提高的原因之...
  • ones123654
  • ones123654
  • 2015-11-26 11:04
  • 240

产品成长三步曲

产品成长三步曲 – 来看下你的产品处在哪一步 原文链接: http://www.huxiu.com/article/111462/1.html 你先会想要使用它, 然后你会需要它, 最后大家会变得离不开它 - 就像一个融入到人们日常生活中的到处可见的实用工具一样。 当前Faceb...
  • fireroll
  • fireroll
  • 2015-05-11 15:29
  • 381

OpenCV-2.4.2 安装三步曲

注意:本人未使用  ffmpeg 的全部依赖库,比如AAC 音频编码库(libfaac-dev),MP3 编码库(ibmp3lame-dev),具体的配置为: ./configure --enable-shared --enable-gpl --enable-version3 --ena...
  • dyzok88
  • dyzok88
  • 2015-04-20 01:45
  • 4513

测试人员面试三步曲

作者:不详    春节过后,很多测试朋友都想换换工作,找一个待遇好、环境好,又有自己用武之地和发展空间的工作。在此,我将自己招聘和面试的一些经验与心得汇成三步曲,献给大家,希望对大家找工作能有所帮助。  第一步、投递简历   投递...
  • chicochen
  • chicochen
  • 2006-12-24 11:11
  • 1077

三步曲之柳时元

PART 1雪柳 冬日的柳独自垂髫感到冷寒时已是秋过雁南 冬日的柳独自瑟瑟情愿覆盖雪银以此取暖 冬日的柳听闻爱是太阳被爱是热 自此抿上嘴角隐隐憨笑眯上眼角默默温润 冬日的柳素裹银装雪色童心  PART 2羁石 具像的时间...
  • seshi_won
  • seshi_won
  • 2004-12-05 22:19
  • 440

投资三步曲后记

                投资三步曲后记     终于写完了。写完了对于我来说是巨篇的三篇心得文章,它的...
  • Labber
  • Labber
  • 2009-08-24 23:32
  • 223

高效设计三步曲

设计本就是不局限章法的事情,追求百花齐放,那么灵感的来源自然也就不受限制了,各有各的道理。但是设计不=艺术, 要的是众乐乐.是为了让想法最终变为现实,要求的是结果,否则方案永远会停留在概念阶段而不可实施。 既然如此,如何成体系的思考 , 高效完成设计并对产品的最终形态负责任?这里总结了高效设计三步曲...
  • dlfeicui
  • dlfeicui
  • 2017-12-18 15:25
  • 22
    个人资料
    • 访问:3937506次
    • 积分:56607
    • 等级:
    • 排名:第57名
    • 原创:1462篇
    • 转载:83篇
    • 译文:1篇
    • 评论:3787条
    博客专栏
    文章存档
    最新评论