Facebook POP 动画框架 进阶指南

2024-06-04 06:38

本文主要是介绍Facebook POP 动画框架 进阶指南,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://www.cocoachina.com/industry/20140704/9034.html

http://www.cocoachina.com/ios/20140508/8352.html

http://www.cocoachina.com/industry/20140507/8339.html



阅读器

Facebook Pop

本文转自Kevin Blog

 

Facebook 在发布了 Paper 之后,似乎还不满足于只是将其作为一个概念性产品,更进一步开源了其背后的动画引擎 POP,此举大有三年前发布的 iOS UI 框架 Three20 的意味。而 POP 开源后也不负 Facebook 的厚望。

 

POP背后的开发者是  Kimon Tsinteris, Push Pop Press 的联合创始人,曾经在Apple担任高级工程师,并参与了 iPhone 和 iPad 上软件的研发(iPhone的指南针以及地图)。2011年的时候 Facebook 收购了他的公司,此后他便加入了 Facebook 负责 Facebook iOS 版本的开发。
如果你打开 Push Pop Press 开发的 AI Gore 这款 App,你会发现交互和动画与Paper几乎如出一辙。对,他们都是 Kimon Tsinteris 开发的。
不满于 Apple 自身动画框架的单调,Push Pop Press 致力于创造一个逼真的、充满物理效应的体验。 POP 就是这个理念下最新一代的成果。
POP 使用 Objective-C++ 编写,Objective-C++ 是对 C++ 的扩展,就像 Objective-C 是 C 的扩展。而至于为什么他们用 Objective-C++ 而不是纯粹的 Objective-C,原因是他们更喜欢 Objective-C++ 的语法特性所提供的便利。
POP 的架构
POP 目前由四部分组成:1. Animations;2. Engine;3. Utility;4. WebCore。
POP 动画极为流畅,其秘密就在于这个 Engine 中的POPAnimator 里,POP 通过 CADisplayLink 高达 60 FPS 的特性,打造了一个游戏级的动画引擎。
CADisplayLink 是类似 NSTimer 的定时器,不同之处在于,NSTimer 用于我们定义任务的执行周期、资料的更新周期,他的执行受到 CPU 的阻塞影响,而 CADisplayLink 则用于定义画面的重绘、动画的演变,他的执行基于 frames 的间隔。
通过 CADisplayLink,Apple 允许你将 App 的重绘速度设定到和屏幕刷新频率一致,由此你可以获得非常流畅的交互动画,这项技术的应用在游戏中非常常见,著名的 Cocos-2D 也应用了这个重要的技术。
WebCore 里包含了一些从 Apple 的开源的网页渲染引擎里拿出的源文件,与 Utility 里的组件一并,提供了 POP 的各项复杂计算的基本支持。
由此通过 Engine、Utility、WebCore 三个基石,打造了Animations。
POPAnimation 有着和 CALayer 非常相似的 API。如果你知道 CALayer 的动画 API,那么你对下面的接口一定非常熟悉, 想必你一定开始迫不及待想试试 POP 了,我们现在就 Jump right in。
因为篇幅原因,下面的代码并不是完整代码,你可以到  https://github.com/kevinzhow/pop-handapp 获取我们的示例 App 。
基本类型
Spring Animation
ease-in ease-out 这些可能你已经非常熟悉,这是动画的动作标配了,不过 POP 觉得只是这样显然太无聊,提供了两个非常不同于其的动画模式,第一个就是 Spring Animation。
Spring Animation 由诸多的复杂参数来控制,展现了一个非常风骚的姿势。
* Bounciness 反弹-影响动画作用的参数的变化幅度
* Speed 速度
* Tension 拉力-影响回弹力度以及速度
* Friction 摩擦力-如果开启,动画会不断重复,幅度逐渐削弱,直到停止。
* Mass 质量-细微的影响动画的回弹力度以及速度
Tension,Friction,Mass 这三个参数的作用很微妙,需要你在示例程序里去仔细体会。
使用 Spring Animation 的方式非常简单。
     
  1. POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 
  2. anim.toValue = [NSValue valueWithCGPoint:CGPointMake(2.0, 2.0)]; 
  3. anim.springBounciness = 4.0; 
  4. anim.springSpeed = 12.0; 
  5. anim.completionBlock = ^(POPAnimation *anim, BOOL finished) { 
  6.   if (finished) {NSLog(@"Animation finished!");}}; 
通过 [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY] 我们创建了一个二维平面上分别沿着 X 和 Y 坐标轴进行缩放的动画。
因此我们要使用 toValue 来告诉 POP 我们希望分别缩放几倍,如果你不提供 fromValue,那么 POP 将默认从当前的大小为依据进行缩放。值得一提的是,toValue 这里的值要和动画作用的属性一样的结构。如果我们操作 bounds ,那么这里应该是 [NSValue valueWithCGRect:CGRectMake(0.0, 0.0, 200.0,400.0)]。
completionBlock 提供了一个 Callback,动画的执行过程会不断调用这个 block,finished 这个布尔变量可以用来做动画完成与否的判断。
最后我们使用 pop_addAnimation 来让动画开始生效,如果你想删除动画的话,那么你需要调用 pop_removeAllAnimations 。 与 iOS 自带的动画不同,如果你在动画的执行过程中删除了物体的动画,那么物体会停在动画状态的最后一个瞬间,而不是闪回开始前的状态。
Decay Animation
Decay Animation 就是 POP 提供的另外一个非常特别的动画,他实现了一个衰减的效果。这个动画有一个重要的参数 velocity(速率),一般并不用于物体的自发动画,而是与用户的交互共生。这个和 iOS7 引入的 UIDynamic 非常相似,如果你想实现一些物理效果,这个也是非常不错的选择。
Decay 的动画没有 toValue 只有 fromValue,然后按照 velocity 来做衰减操作。如果我们想做一个刹车效果,那么应该是这样的。
     
  1. POPDecayAnimation *anim = [POPDecayAnimation animWithPropertyNamed:kPOPLayerPositionX]; 
  2. anim.velocity = @(100.0); 
  3. anim.fromValue =  @(25.0); 
  4. //anim.deceleration = 0.998; 
  5. anim.completionBlock = ^(POPAnimation *anim, BOOL finished) { 
  6.   if (finished) {NSLog(@"Stop!");}}; 
这个动画会使得物体从 X 坐标的点 25.0 开始按照速率 100点/s 做减速运动。 这里非常值得一提的是,velocity 也是必须和你操作的属性有相同的结构,如果你操作的是 bounds,想实现一个水滴滴到桌面的扩散效果,那么应该是 [NSValue valueWithCGRect:CGRectMake(0, 0,20.0, 20.0)]
如果 velocity 是负值,那么就会反向递减。
deceleration (负加速度) 是一个你会很少用到的值,默认是就是我们地球的 0.998,如果你开发给火星人用,那么这个值你使用 0.376 会更合适。
Property Animation & Basic Animation
POP 号称可以对物体的任何属性进行动画,其背后就是这个 Property Animation驱动。Spring Animation 和 Decay Animation 都是继承自这个类,接下来我们通过一个 Counting Label 的例子来展现这个神奇的能力。
与此同时我们也使用了 Basic Animation,经典的 ease-in-out 此刻发挥了重要的作用,因为我们并不需要计数器的数值进行回弹。
     
  1. POPBasicAnimation *anim = [POPBasicAnimation animation]; 
  2. anim.duration = 10.0; 
  3. anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
  4. POPAnimatableProperty * prop = [POPAnimatableProperty propertyWithName:@"count" initializer:^(POPMutableAnimatableProperty *prop) { prop.readBlock = ^(id obj, CGFloat values[]) { 
  5.     values[0] = [[obj description] floatValue];}; 
  6.   prop.writeBlock = ^(id obj, const CGFloat values[]) { 
  7.     [obj setText:[NSString stringWithFormat:@"%.2f",values[0]]];}; 
  8.   prop.threshold = 0.01;}]; 
  9. anim.property = prop; 
  10. anim.fromValue = @(0.0); 
  11. anim.toValue = @(100.0); 
POPBasicAnimation 的 timingFunction 我们定义了动画的方式,慢开慢停。随后通过 POPAnimatableProperty 定义了 POP 如何操作 Label 上的数值。
readBlock 中,obj 就是我们的 Label,values 这个是动画作用的属性数组,其值必须是 CGFloat ,之前我们在 Decay Animation 中操作了 bounds
那么 values[0],values1,values2,values3 就分别对应 CGRectMake(0, 0, 20.0, 20.0) 的 0, 0, 20.0, 20.0
这里我们只需要操作 Label 上显示的文字,所以只需要一个参数。通过 values[0] = [[obj description] floatValue] 我们告诉 POP 如何获取这个值。
相应的我们通过 [obj setText:[NSString stringWithFormat:@”%.2f”,values[0]]] 告诉了 POP 如何改变 Label 的属性。
threshold 定义了动画的变化阀值,如果这里使用 1,那么我们就不会看到动画执行时候小数点后面的数字变化。 到此为止,我们的 Counting Label 就完成了,是不是超简单?
实战
PopUp & Decay Move
这个实例中我们介绍下如何将 Decay 动画和用户的操作结合起来,实现一个推冰壶的效果。
首先我们给我们的物体添加个 UIPanGestureRecognizer 的手势操作其,处理方式如下
     
  1. case UIGestureRecognizerStateChanged: { 
  2.   [self.popCircle.layer pop_removeAllAnimations]; 
  3.   CGPoint translation = [pan translationInView:self.view]; 
  4.   CGPoint center = self.popCircle.center; 
  5.   center.x += translation.x; 
  6.   center.y += translation.y; 
  7.   self.popCircle.center = center; 
  8.   [pan setTranslation:CGPointZero inView:self.popCircle]; 
  9.   break
  10. case UIGestureRecognizerStateEnded: 
  11. case UIGestureRecognizerStateCancelled: { 
  12.   CGPoint velocity = [pan velocityInView:self.view]; 
  13.   [self addDecayPositionAnimationWithVelocity:velocity]; 
  14.   break
  15.  }   
当用户触摸这个冰壶的时候,所有动画会立刻停止,然后跟随用户的手指移动。 通过 [pan velocityInView:self.view]; 我们获取了用户手指移动的速率然后在 addDecayPositionAnimationWithVelocity 中处理动画
     
  1. POPDecayAnimation *anim = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPosition]; 
  2. anim.velocity = [NSValue valueWithCGPoint:CGPointMake(velocity.x, velocity.y)]; 
当用户松开手之后,冰壶会依照地球的重力在低摩擦的状态下前进逐渐停止。如果想增大摩擦力,你可以把速率乘以一个摩擦系数。
Fly In
在这个实例中,我们介绍下如何结合两个动画。实现一个像 Path 的卡片飞入的效果。
同样保留了 Decay Move 的效果,你可以甩走这张卡片。
     
  1. POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY]; 
  2. anim.fromValue = @-200; 
  3. anim.toValue = @(self.view.center.y); 
  4.  
  5. POPBasicAnimation *opacityAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity]; 
  6. opacityAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
  7. opacityAnim.toValue = @1.0; 
  8.  
  9. POPBasicAnimation *rotationAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation]; 
  10. rotationAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
  11. rotationAnim.beginTime = CACurrentMediaTime() + 0.1; 
  12. rotationAnim.toValue = @(0); 
首先把我们的冰壶变成卡片,旋转一点角度。这里需要注意的是,我们使用了 duration 来定义了 Basic Animation 的执行时间,beginTime 来定义了动画的开始时间。beginTime 接受的是一个以秒为单位的时间,所以我们使用了 CACurrentMediaTime() 获取了当前时间,然后加上了延迟时间。
Transform
这个实例是真的酷极了的效果,我们将实现一个用户点击后播放按钮转换为进度条容器的变形效果。
首先我们创建一个进度条,这个真是我最拿手的事情了。通过 lineCap lineWidth 我们调整进度条的样式,然后使用 UIBezierPath 定义了进度条的走向。
     
  1. CAShapeLayer *progressLayer = [CAShapeLayer layer]; 
  2. progressLayer.strokeColor = [UIColor colorWithWhite:1.0 alpha:0.98].CGColor; 
  3. progressLayer.lineWidth = 26.0; 
  4.  
  5. UIBezierPath *progressline = [UIBezierPath bezierPath]; 
  6. [progressline moveToPoint:CGPointMake(25.0, 25.0)]; 
  7. [progressline addLineToPoint:CGPointMake(700.0, 25.0)]; 
  8. progressLayer.path = progressline.CGPath; 
  9.  
  10.  
  11. POPSpringAnimation *scaleAnim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 
  12. scaleAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(0.3, 0.3)]; 
  13.  
  14. POPSpringAnimation *boundsAnim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds]; 
  15. boundsAnim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 800, 50)]; 
  16. boundsAnim.completionBlock = ^(POPAnimation *anim, BOOL finished) { 
  17.   if (finished) {  
  18.      UIGraphicsBeginImageContextWithOptions(self.popCircle.frame.size, NO, 0.0); 
  19.      POPBasicAnimation *progressBoundsAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd]; 
  20.      progressBoundsAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
  21.      progressBoundsAnim.toValue = @1.0; 
  22.      progressBoundsAnim.completionBlock = ^(POPAnimation *anim, BOOL finished) {if (finished) {UIGraphicsEndImageContext();}};   
  23.      [progressLayer pop_addAnimation:progressBoundsAnim forKey:@"AnimateBounds"]; 
  24.    } 
  25.  }; 
首先是一起进行的 scale 和 bounds 的变化效果,播放按钮将缩小然后改变外形成为进度条的容器,在变形结束后,我们触发进度条的动画。
这里我们使用 UIGraphicsBeginImageContextWithOptions(self.popCircle.frame.size, NO, 0.0); 开启了绘画上下文,动画结束后使用 UIGraphicsEndImageContext(); 清空了绘画上下文。这个主要是影响了画板的大小。
这里我们没有使用 UIGraphicsBeginImageContext() 而是使用 UIGraphicsBeginImageContextWithOptions() 以此获取一个更清晰的绘图效果。
值得关注的 POP 周边
POP-HandApp  这就是本文的示例App,包含了大量动画的操作方法和上述介绍的实例。
AGGeometryKit-POP  通过 POP 对图片进行变形操作,非常酷。
POP-MCAnimate  POP 的一个封装,可以让你更方便的使用 POP。
Rebound  POP 的 Android 部分实现,主要是 Spring 的效果,移植自 Facebook 的rebound-js。
结语
POP 是一个新的里程碑,通过 POP,动画的开发门槛大大降低,并且实现了丰富的属性操作,其倡导的可中断式动画交互会革命性也值得我们仔细研究体会,想必不久就会涌现大量富有活力的 App ,感谢 Facebook,感谢开源。 Long live Opensource.

这篇关于Facebook POP 动画框架 进阶指南的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1029338

相关文章

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

打造坚固的SSH防护网:端口敲门入门指南

欢迎来到我的博客,代码的世界里,每一行都是一个故事 🎏:你只管努力,剩下的交给时间 🏠 :小破站 打造坚固的SSH防护网:端口敲门入门指南 前言什么是端口敲门端口敲门的优点1. 增强安全性2. 动态防火墙规则3. 隐匿服务4. 改善日志管理5. 灵活性和兼容性6. 低资源消耗7. 防御暴力破解和扫描8. 便于合法用户访问9. 适用于不同类型的服务 端口敲

[分布式网络通讯框架]----Zookeeper客户端基本操作----ls、get、create、set、delete

Zookeeper数据结构 zk客户端常用命令 进入客户端 在bin目录下输入./zkCli.sh 查看根目录下数据ls / 注意:要查看哪一个节点,必须把路径写全 查看节点数据信息 get /第一行代码数据,没有的话表示没有数据 创建节点create /sl 20 /sl为节点的路径,20为节点的数据 注意,不能跨越创建,也就是说,创建sl2的时候,必须确保sl

【服务器08】之【游戏框架】之【加载主角】

首先简单了解一下帧率 FixedUpdate( )   >   Update( )   >   LateUpdate( ) 首先FixedUpdate的设置值 默认一秒运行50次 虽然默认是0.02秒,但FiexedUpdate并不是真的0.02秒调用一次,因为在脚本的生命周期内,FixedUpdate有一个小循环,这个循环也是通过物理时间累计看是不是大于0.02了,然后调用一次。有

Java中的集合框架使用技巧

Java中的集合框架使用技巧 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Java中集合框架的使用技巧,这些技巧能够帮助我们更高效地处理数据和优化程序性能。 Java集合框架概述 Java集合框架提供了一组实现了各种集合接口的类和接口,用于存储和操作数据。它包括列表、集合、队列和映射等数据结构,能够满足不

[分布式网络通讯框架]----ZooKeeper下载以及Linux环境下安装与单机模式部署(附带每一步截图)

首先进入apache官网 点击中间的see all Projects->Project List菜单项进入页面 找到zookeeper,进入 在Zookeeper主页的顶部点击菜单Project->Releases,进入Zookeeper发布版本信息页面,如下图: 找到需要下载的版本 进行下载既可,这里我已经下载过3.4.10,所以以下使用3.4.10进行演示其他的步骤。

C# 日志框架Serilog使用

1、框架和说明        C#日志框架Serilog支持多种场景输出,简单验证了一下,比较方便        包的安装,推荐直接使用“推荐NuGet包管理器”安装Serilog.AspNetCore,常见的组件都已经集成在一个包中,使用比较方便 2、配置文件        Serilog可以由配置文件来定义行为,而且配置文件的修改即时生效。参考配置文件如下: {"Serilog":

Pytest和Unitest框架对比

在学到自动化的时候,很多同学都遇到了Pytest和Unitest框架,有的人是两个都学,但是学的不精只是知道分别怎么用.不了解两个区别是什么.有的是犹豫到底要学习那个框架.其实要做好自动化测试,是有必要了解不同框架之间的差异化的. Pytest 特点: Pytest采用了更简洁、更灵活的语法风格,使用“assert”语句来进行断言,Pytest可以自动发现并执行以“test_”开头的函数

mysql-mmm框架2

简介 MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM使用Perl语言开发,主要用来监控和管理MySQL Master-Master(双主)复制,虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热,可以说MMM这套脚本程