您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
Facebook POP,迈向大师操作之路
 
作者 周楷雯 火龙果软件  发布于 2014-06-05
 

Facebook发布Paper之后,似乎还不满足于只是将其作为一个概念性产品,反而更进一步开源了其背后的动画引擎POP(https://github.com/facebook/pop),此举大有三年前发布的iOS UI框架Three20(https://github.com/facebookarchive/three20)的意味。而POP开源后不负Facebook的厚望,在GitHub上不足一个月的时间,就已拥有了6000多个Star,非常火爆。

POP背后的开发者是Kimon Tsinteris,他是Push Pop Press的联合创始人,曾在苹果担任高级工程师,并参与了iPhone和iPad上的软件研发(iPhone的指南针及地图)。2011年,Facebook收购了他的公司,此后他便加入了Facebook负责Facebook iOS版本的开发。

如果你打开Push Pop Press开发的《AI Gore》这款App,就会发现它的交互和动画与Paper几乎如出一辙,原因就在于,它们都是由Kimon Tsinteris开发的。由于不满足于苹果自身动画框架的单调,Push Pop Press致力于创造一个逼真的、充满物理效应的体验。POP就是在这个理念下催生出来的新一代成果。

POP使用Objective-C++编写。Objective-C++是对C++的扩展,就像Objective-C是C的扩展一样。而至于为什么他们用Objective-C++而不是纯粹的Objective-C,原因在于他们更喜欢Objective-C++的语法特性所提供的便利。

POP的架构

POP目前由四个部分组成(如图1所示),即Animations、Engine、Utility、WebCore。

;

图1 POP架构图

POP动画极为流畅,其秘密就在于这个引擎中的POPAnimator。POP通过CADisplayLink让动画实现了60 FPS的流畅效果,打造了一个游戏级的动画引擎。

CADisplayLink是类似NSTimer的定时器,不同之处在于,NSTimer用于我们定义任务的执行周期及资料的更新周期,它的执行受CPU的阻塞所影响。而CADisplayLink则用于定义画面的重绘和动画的演变,它的执行是基于Frames的间隔。通过CADisplayLink,苹果允许开发者将App的重绘速度设定到与屏幕刷新频率一致。因此开发者可以获得非常流畅的交互动画,这项技术的应用在游戏中非常常见,著名的Cocos-2d引擎也用到了这个重要的技术。

WebCore里包含了一些从苹果的开源的网页渲染引擎里拿到的源文件(http://opensource.apple.com/source/WebCore),它与Utility里的组件一并为POP的各项复杂计算提供了基本支持。因此,通过Engine、Utility、WebCore三个基石,打造了Animations。

POPAnimation有着与CALayer非常相似的API。如果你知道CALayer的动画API,那么你对下面的接口一定非常熟悉。说到这里,想必你一定开始迫不及待地想试试POP了(因篇幅所限,下面的代码并不是完整代码,你可以到https://github.com/kevinzhow/pop-handapp获取示例App)。

基本类型

·Spring Animation

图2 默认的两种动画模式以及他们的动画节奏

POP默认提供了两个非常特别的动画模式,第一个就是Spring Animation(如图2所示),另一个是Decay Animation。让我们先来看看Spring Animation,控制其动画效果的主要参数包括:

·Bounciness反弹,影响动画作用的参数的变化幅度;

·Speed速度;

·Tension拉力,影响回弹力度及速度;

·Friction摩擦力,开启后,动画会不断重复,并且幅度逐渐削弱,直到停止;

·Mass质量,细微地影响动画的回弹力度和速度。

实际上,Tension、Friction、Mass这三个参数的作用很微妙,需要在示例程序中仔细体会。使用Spring Animation的方式非常简单,如代码1所示。

代码1

通过[POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]我们创建了一个在二维平面上分别沿着X轴和Y轴进行缩放的动画。

下面我们介绍三个重要的参数。

·fromValue将告诉POP物体被动画操作的属性从什么数值开始运行。如果不提供fromValue,那么POP将默认使用当前数值。在这个例子中,就默认使用当前的比例。

·toValue是我们希望动画结束后,物体被动画操作的属性停留在什么值上,在这个例子中,toValue告诉了POP,我们希望沿着X轴和Y轴各缩放几倍。

·completionBlock提供了一个Callback,动画的执行过程会不断调用这个block,finished这个布尔变量可以用来做动画完成与否的判断。

值得一提的是,这里toValue和fromValue的值应该和动画所作用的属性是一样的数据结构。例如,如果我们的操作对象是bounds,那么这里的toValue则应该是[NSValue valueWithCGRect:]。

最后,我们使用pop_addAnimation来让动画开始生效,如果想删除动画的话,那么需要调用pop_removeAllAnimations。

与iOS自带的动画不同,如果你在动画的执行过程中删除了物体的动画,那么物体会停在动画状态的最后一个瞬间,而不是闪回开始前的状态。

·Decay Animation

Decay Animation可以实现衰减的动画效果。这个动画有一个重要的参数即velocity(速率),这个参数一般并不用于物体的自发动画,而是与用户的交互共生。这和iOS 7引入的UIDynamic非常相似,如果你想实现一些物理效果,Decay Animation也是不错的选择。

Decay的动画没有toValue只有fromValue,以fromValue作为原始值,按照velocity来做衰减操作。如果我们想做一个刹车效果,则可以像代码2这样操作:

代码2

这个动画会使得物体从X坐标的25.0开始做100点/秒的减速运动。如果velocity里的数字是负值,那么你的动画就会反方向执行动画效果。这里非常值得一提的是,velocity也是必须和你操作的属性有相同的数据结构,如果你操作的是bounds,想实现一个水滴滴到桌面的扩散效果,那么velocity则应该是[NSValue valueWithRect:CGRectMake(0, 0, 20, 20)]。

deceleration(负加速度)是一个很少用到的值,它影响动画被重力影响的效果。默认值就是我们地球的重力加速度0.998。如果你程序里的动画开发给火星人看,那么使用0.376这个值会更合适。

·Property Animation和Basic Animation

POP号称可以对物体的任何属性进行动画,其背后就是这个PropertyAnimation驱动。Spring Animation和Decay Animation都是继承自这个类,接下来我们通过一个Counting Label的例子来演示Property Animation的神奇能力。在这个动画中,我们也使用了Basic Animation,动画模式是经典的ease-in-out,不使用Spring Animation是因为我们并不需要计数器的数值进行回弹,如代码3所示。

代码3

通过POPBasicAnimation的timingFunction我们定义了动画的展现方式——渐入渐出。随后通过POPAnimatableProperty来定义POP如何操作Label上的数值。

这里我们需要注意两个函数,readBlock和writeBlock。readBlock定义了动画如何获取要操作的属性数值,writeBlock定义了动画如何修改要操作的属性数值。在这两个函数中,obj就是我们的Label,values是动画所操作的属性数组,其值必须是CGFloat。

你可能会问,什么是动画所操作的属性数组?回顾之前我们在Decay Animation中操作的bounds内容,可以看出values[0]、values[1]、values[2]、values[3]分别对应了CGRectMake(0, 0, 20.0, 20.0)的0、0、20.0、20.0。这里我们需要操作Label上显示的文字,所以只需要一个values[0]属性即可。

通过values[0]=[[obj description] floatValue]我们告诉POP如何获取这个值。相应地,我们通过[obj setText:[NSString stringWithFormat:@"%.2f",values[0]]],告诉POP如何改变Label的属性。

threshold定义了动画的变化阀值,如果这里使用1,那么我们就不会看到动画执行时小数点后面的数字变化。

到这里,我们的Counting Label就完成了,是不是超简单?

实战

·PopUp和Decay Move

这个实例中,我将介绍一下如何将Decay动画和用户的手势操作结合起来,实现一个推冰壶的效果。手势的处理方式如代码4所示。

代码4

当用户触摸这个冰壶时,所有动画会立刻停止,然后冰壶会跟随用户的手指移动。在用户松开冰壶时,通过[pan velocityInView:self.view]我们获取了用户手指移动的速率,在addDecayPositionAnimationWithVelocity中生成动画,如代码5所示。

代码5

动画生效后,冰壶就会在低摩擦的状态下前进并逐渐停止。如果想增大摩擦力,则可以将速率乘以摩擦系数。

·Fly In

在这个实例中,我将介绍一下如何将两个动画相结合,实现一个像Path中卡片飞入的效果。如代码6所示。

代码6

第一个Spring Animation实现了卡片下落的效果,第二个Basic Animation实现了卡片的渐入效果,而最后的一个Basic Animation则实现了卡片倾斜的效果。

这里需要注意的是,我们使用了duration来定义Basic Animation的执行时间,并用beginTime来定义动画的开始时间。beginTime接受的是一个以秒为单位的时间,所以我们使用了CACurrentMediaTime()来获取当前的时间,在此之上增加上了期望动画延迟的时间。

·Transform

这个实例真的酷极了,我们将实现一个用户点击后播放按钮转换为进度条容器的变形效果。首先创建一个进度条,通过lineCap lineWidth调整进度条的样式,然后使用UIBezierPath来定义进度条的走向,如代码7所示。

代码7

代码8就是实现变形的代码。从这段代码不难看出,scale和bounds的变化效果是一起进行的。这时,播放按钮将缩小,然后改变外形成为进度条的容器。在变形结束后,将触发进度条的动画。

代码8

这里我们使用UIGraphicsBeginImageContext-WithOptions()去开启绘画上下文,动画结束后使用UIGraphicsEndImageContext()来清空绘画的上下文。这两个函数主要是影响画板的大小。

   
次浏览       
相关文章

用户故事与用例
交互设计师之精益画布篇
数据分析之用户画像方法与实践
如何快速建立用户模型?
 
相关文档

用户界面设计
给企业做大数据精准用户画像
用户体验和交互设计
大数据下的用户画像
相关课程

用户体验&界面设计
用户体验、易用性测试与评估
用户研究与用户建模
用户体验的软件UI设计最佳实践

从手机登录页面设计想到的
如何把无意识引入交互设计中
交互设计的真相
当视觉设计师遇上产品经理
手机交互设计原则
用户体验之网页板块设计
更多...   

以用户为中心的设计
可用性评估
Desktop及Web-based视觉设计
认知原理与设计应用
手机用户界面设计

北京 以用户为中心的界面设计
北京 用户体验& 界面设计
上海 华为 用户体验& 界面设计
深圳 用户体验& 界面设计
爱立信 以用户为中心的设计
北京 用户体验与界面设计
福州 以用户为中心的界面设计
更多...