zoukankan      html  css  js  c++  java
  • iOS动画一点也不神秘————你是喜欢看幻灯片?还是看高清电影?

    iOS设备在平均线上硬件比andorid设备良好许多,尤其是内存和CPU,所以iOS应用里面有大量动画交互效果的交互,这是每个用户都喜悦的,如果每个操作对应界面来讲都是直接变化,那变得十分地生硬。

    你是喜欢看幻灯片?还是看高清电影?我想如果能让用户选择的话,这个问题简直不必问,如果你去下载一个XXX的高清五码种子,结果发现下载下来是个PPT,你会如何想。

    虽然幻灯片里面也有动画效果,但是作为举例来讲我们只当做他是一张张直接切换,而电影是连续的,有视觉代入感的,有情景的,有很强的上下文的!

    如果我们的交互效果没有动画,那么用户的体验应该如何,我们做如下设想:

    1. 用户点击按钮A
    2. 按钮A事件触发,此时视图B将屏幕盖住。

    对于用户来讲,从手指从按钮上松开到视图B将屏幕整个盖住,这个过程几乎是瞬间完成,中间不会任何过度,没有时间让用户反应过来整个屏幕已经完全变了。即使B视图的内容非常庞大,需要一段时间才能出现,那用户也无非是多看0.x秒的A,然后马上一下子看到B视图盖住屏幕。

    如果是一个APP里面,有很多选项,手势,按钮,页面跳转,那作为用户来讲他的心情无异于看幻灯片,而不是看流畅的电影。

    所以幻灯片和电影从本质来讲一个是直接的全屏替换,一个是逐帧地变幻。

    一个帧数接近于0,一个帧数是在人眼舒适的范围内。起码10帧/每秒。

    所以我们要在APP里面加入动画,比如B视图将屏幕盖住,是从下方滑入?翻转?淡入?索性这些都有现成的API供我们调用,非常轻松。我们要加个动画的目的是什么?给用户代入感与情景感。


    即让用户知道B是盖在了A的上面,而不是把A直接删除了,或者场景直接切换了。

    就跟我们接触的最多的上下文Context一个道理,人机交互的时候机器以图形界面对人的操作做出相应的过程如果逐帧地进行,那么这个上下文是连续,是直观反映的。


    再回到手机的角度来看这个动画过程。既然要逐帧地进行“B盖住屏幕”这件事,那无非就是让这个过程的帧数控制在24帧左右让人言无法分辨:每时每秒都在走一点点,最后盖住了整个屏幕。那么手机本身是有刷新率的,就拿PC的显示器来讲,配置差一点的显示器你是可以看到例如拖动一个窗口,这个窗口不是连续跟着鼠标走而是断断续续走的。手机也是有显卡的,就拿PC的显卡来讲,256M的显卡能玩《魔兽世界》吗?《英雄联盟》?即使能我估计你可以看幻灯片了!

    看幻灯片 这个词在魔兽世界用户的使用下才有了我今天表达的这个意义:"下个副本卡的跟幻灯片似的!"那么这个玩家的显卡一般来说会是低端显卡。然后就是内存了。刷新率、显存、内存 他们不同程度上影响用户的体验,好在iOS设备硬件的跨度小,所以我们开发者还算幸运不用考虑太多,在差不多的配置下,同一个动画的流畅性是差不多的。

    具体手机怎样实现这个动画?

    其实手机无时无刻不在上演动画。

    为什么这么说,我们常常说动画,按字面理解可以理解为会动的图像,那么手机屏幕他不是纸,他是可以动的,他有他的刷新率,他每时每刻都在疯狂地刷新自己,来维持图像,即使内容是静止的。所有的屏幕都有刷新率。

    而我们"B从下往上盖住屏幕"这样的东西,只能算是在屏幕高速刷新的过程中,顺便在每1次/N次刷新的时候一起渲染出来而已。

    注意,是顺便渲染一下,是真的。

    至于这个是每多少次渲染一下,就和我们的帧数、屏幕的刷新率通过简单的式子计算了。那么对于假定刷新率2400次/秒,屏幕高度480像素的手机来讲,给定这个动画的哪些条件,他就能完成这个持续1秒的动画?


    1.最严苛的条件,直接与刷新率相同,即给出B从下往上盖住屏幕的过程中的2400次状态,那么屏幕每刷新一次就变化一次。用户看起来是连贯的。

    但是其实用户的眼睛没有那么敏感。这个数值太高会铺张浪费造成额外开销。

    2.按照电影标准,即给出B从下往上盖住屏幕的过程中的24次状态,那么屏幕每刷新(你可以理解为屏幕每闪一下,屏幕其实是会闪的,只是间隔太小你看不到,详细原因请百度“视觉停留效果”)2400/24=100 次的时候,状态就变幻一次。

    那么列出来可能:(手机每0.0004166666秒刷新一次,那么刷新100次的间隔是每0.0041666秒,令k=0.00416666秒)

    第0~k秒之间,B的位置处于屏幕底部,伸出480/24=20像素

    第k~2k秒之间,B的位置处于屏幕底部,伸出40像素

    第2k~3k秒之间,B的位置处于屏幕底部,伸出60像素

    第n*k~(n+1)*k秒之间,B的位置处于屏幕底部,伸出20*(n+1)像素

    第1.0秒,B完全盖住屏幕,高度为480像素。


    第二种效果是可行的!虽然有一点浪费,在这个例子中,但是在其他很多例子中他是很实用的。在IOS中,这种动画叫做“关键帧动画”,负责这个动画的核心类叫做CAKeyFrameAnimation。

    但是实际是我们还是太曲折了,不就是从底部到顶部吗?根本不需要知道每一个个状态的具体像素高,因为他们都是有规律的!你看!20*(n+1)!多么优雅的式子,难道计算机不会吗?要我们一个个告诉他?学过flash的同学都知道,这种完全规律的变化根本就不叫关键帧,叫做补间帧。所以,继续看

    是的,计算机没有这么蠢,这个明显是一个连续的、遵循唯一递推规律的变化,所以计算机根本不需要这么详细。实际上我们只需要告诉计算机从哪里,到哪里。就行了。充其量再加一个,经过哪里。

    在IOS中,我们简化这个动画,让他只保留更关键的信息。

    3.给出比关键帧更关键的帧:起点-中点-终点。

    当然最后计算渲染出来肯定不是只有3个帧,他的帧数应该还是24以上,但是我们只给这3个帧给计算机,他那么聪明,自己是足够计算出其他的21帧然后帮你补上去的。

    这种动画叫做 "基础动画",他的核心类叫做CABasicAnimation。


    但是我们常常发现这样还不够简单啊,对于这个情况,起点(fromValue)是在屏幕底部,中点(byValue)是屏幕中间,终点(toValue)是达到屏幕顶部。

    如果我们修改条件,让B在A按钮按下来之前一直处于屏幕下方看不见的位置,刚好顶着屏幕底部。

    问:起点能不是屏底部吗?

    其实在动画开始前,B本来就在屏幕底部啊,所以我们这个起点在屏幕外,是不是废话呢?

    如果我们的运动是线性的,他经过的地方能不是屏幕终点吗?

    所以CABasicAnimation的参数是可以选择性传的。对于这个修改后的例子我们只需要一个信息。其他两个废话都可以不用告诉计算机:

    B移动到屏幕顶部去。

    伪代码:

    anim setToValue:屏幕顶部

    b.addAnimation:anim

    计算机由于不知道B要从哪儿移动到屏幕底部去,那么自然就认为你是要B从当前位置,按照线性变化到屏幕顶部去。

    所以对于给定位置的layer来讲,我们要让其添加CABasicAnimation,可以只设置一个value。那么看到的效果计算会自动帮我们补成完整的动画:

    fromValue=当前位置<-->byValue=距离的一半<-->toValue=屏幕顶部

    当这个唯一Value 是FromValue的时候,如果当前位置与FromValue不相等,我们也是看到一段完整的动画:

    fromValue=屏幕任意位置<-->byValue=距离的一半<-->toValue=当前位置


    弄清楚这两个动画类的本质之后,你可以理解为任何函数,添加任何动画,道理都类似:告诉你算计动画的规律,然后计算机还是会根据你告诉他的关键信息/规律,渲染出每秒24帧以上的图像出来!

    请看下回分析Layer层动画,View层动画,以及Transform3D一点也不神秘

  • 相关阅读:
    剑指 Offer 41. 数据流中的中位数
    剑指 Offer 19. 正则表达式匹配
    leetcode 75 颜色分类
    Deepin 添加 open as root
    window 下 无损进行其他文件系统(ext4) 到 ntfs 文件系统的转化
    Windows Teminal Preview Settings
    CentOS 7 容器内替换 apt-get 源为阿里源
    Ubuntu 20.04 安装 Consul
    elementary os 15 添加Open folder as root
    elementary os 15 gitbook install
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3339356.html
Copyright © 2011-2022 走看看