您现在的位置是:首页 > 文章详情

iOS 开发之使用 Facebook POP

日期:2018-09-30点击:288

需要打造游戏级别的动画效果?

Facebook 开源的 POP 是一个在 iOS 与 OS X 上通用的极具扩展性的动画引擎,它在基本的静态动画的基础上增加的弹簧动画与衰减动画。

POP 通过 CADisplayLink 将 APP 的重绘速度提高到跟屏幕刷新频率一致的 60 FPS !从而提供游戏级别的动画引擎,由此我们可以创造出更真实、更具物理性、更流畅的交互动画!

没有对比就没有伤害,感兴趣的的同学可以看一下 纯洁的小袋子
的“ Core Animation & Facebook's POP 对比” 。

POP 的架构

POP 目前由四部分组成:

  • Animations
  • Engine
  • Utility
  • WebCore
img_022ff9ea36d962f10daea25a69f3999c.png
Facebook POP

WebCore 里包含了一些从 Apple 的开源的网页渲染引擎里拿出的源文件,与 Utility 里的组件一并,提供了 POP 的各项复杂计算的基本支持。

由此通过 Engine、Utility、WebCore 三个基石,打造了Animations。

POP 提供的动画类

  • POPAnimation(动画的抽象基类)
  • POPBasicAnimation (基本动画类)
  • POPSpringAnimation (弹性动画类)
  • POPDecayAnimation (衰减动画类)
  • POPCustomAnimation (自定义动画类)
  • POPAnimatableProperty (自定义属性动画)
  • POPPropertyAnimation(自定义属性动画)

动画的抽象基类 POPAnimation

#import <Foundation/NSObject.h> #import <pop/POPAnimationTracer.h> #import <pop/POPGeometry.h> @class CAMediaTimingFunction; /** 动画的抽象基类. */ @interface POPAnimation : NSObject /** 动画的名称 根据这个属性用来区别动画;识别动画 */ @property (copy, nonatomic) NSString *name; /** 动画的开始时间; 默认是从0开始启动 */ @property (assign, nonatomic) CFTimeInterval beginTime; /** 动画的 delegate 详情查看查看[POPAnimationDelegate] */ @property (weak, nonatomic) id delegate; /** 动画的追踪器 记录所有动画相关事件,还允许完成后对其进行查询和分析;更多可以查看 [POPAnimationTracer.h] */ @property (readonly, nonatomic) POPAnimationTracer *tracer; /** 动画开始的时候回调的block */ @property (copy, nonatomic) void (^animationDidStartBlock)(POPAnimation *anim); /** 动画达到toValue或者超过值的时候调用的block */ @property (copy, nonatomic) void (^animationDidReachToValueBlock)(POPAnimation *anim); /** 动画完成的时候调用的block */ @property (copy, nonatomic) void (^completionBlock)(POPAnimation *anim, BOOL finished); /** 正在做动画的时候调用;调用次数比较多 */ @property (copy, nonatomic) void (^animationDidApplyBlock)(POPAnimation *anim); /** 完成动画的时候是否删除动画; 默认为YES; 设置NO的话 */ @property (assign, nonatomic) BOOL removedOnCompletion; /** 动画是否已暂停; 在初始化的时候,默认YES;在动画添加的时候,隐式暂停???在动画完成的时候和 removedOnCompletion = NO 的时候,动画是暂停的; */ @property (assign, nonatomic, getter = isPaused) BOOL paused; /** 动画是否逆转;比如向前的动画,做完之后,会再后退回来; 注意:时间是原来的 2 倍,动画到 toValue 后,又回到原始的值; delegate 跟再做一次动画一样; */ @property (assign, nonatomic) BOOL autoreverses; /** 重复动画次数; = 0 或者 1 不会重复; 注意: delegate 中 animationDidStart:每次动画重复开头调用; animationDidReachToValue:每次到 toValue 的时候调用; animationDidStop:finished:每次到 toValue 的时候调用,如果设置了 autoreverses,动画还未完成,返回 NO; 设置了 autoreverses,动画时间是原来 2 倍; */ @property (assign, nonatomic) NSInteger repeatCount; /** 一直重复做动画; delegate 中 animationDidStop 将恒等于 NO; */ @property (assign, nonatomic) BOOL repeatForever; @end @protocol POPAnimationDelegate <NSObject> @optional /** 动画开始的时候调用 */ - (void)pop_animationDidStart:(POPAnimation *)anim; /** 动画达到toValue或者超过的时候调用; */ - (void)pop_animationDidReachToValue:(POPAnimation *)anim; /** 动画停止 */ - (void)pop_animationDidStop:(POPAnimation *)anim finished:(BOOL)finished; /** 正在做动画的时候调用; */ - (void)pop_animationDidApply:(POPAnimation *)anim; @end @interface NSObject (POP) /** 添加动画到接收器; anim:要添加的动画 key:动画标识符,可以是任何字符串,但每个动画必须唯一; */ - (void)pop_addAnimation:(POPAnimation *)anim forKey:(NSString *)key; /** 删除所有附件在接收器上的动画; */ - (void)pop_removeAllAnimations; /** 删除附加在接收器上的所有关键 */ - (void)pop_removeAnimationForKey:(NSString *)key; /** 返回接收器所有动画的 key 的数组;key 的顺序 = 动画顺序; */ - (NSArray *)pop_animationKeys; /** 返回某个 key 的动画,= nil 表示不存在 */ - (id)pop_animationForKey:(NSString *)key; @end /** 实现NSCopying协议; */ @interface POPAnimation (NSCopying) <NSCopying> @end 

基本动画类 POPBasicAnimation

#import <pop/POPPropertyAnimation.h> /** 基础动画 */ @interface POPBasicAnimation : POPPropertyAnimation /** 类创建实例 */ + (instancetype)animation; /** 指定属性动画; */ + (instancetype)animationWithPropertyNamed:(NSString *)name; /** 使用 kCAMediaTimingFunctionDefault 定时功能的基本动画; */ + (instancetype)defaultAnimation; /** @使用 kCAMediaTimingFunctionLinear 定时功能的基本动画; */ + (instancetype)linearAnimation; /** @使用 kCAMediaTimingFunctionEaseIn 定时功能的基本动画; */ + (instancetype)easeInAnimation; /** @使用 kCAMediaTimingFunctionEaseOut 定时功能的基本动画; */ + (instancetype)easeOutAnimation; /** @使用 kCAMediaTimingFunctionEaseIn 定时功能的基本动画; */ + (instancetype)easeInEaseOutAnimation; /** 延迟多少秒执行动画:Defaults to 0.4. */ @property (assign, nonatomic) CFTimeInterval duration; /** 设置动画节奏,默认使用:kCAMediaTimingFunctionDefault CA_EXTERN NSString * const kCAMediaTimingFunctionLinear CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0); CA_EXTERN NSString * const kCAMediaTimingFunctionEaseIn CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0); CA_EXTERN NSString * const kCAMediaTimingFunctionEaseOut CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0); CA_EXTERN NSString * const kCAMediaTimingFunctionEaseInEaseOut CA_AVAILABLE_STARTING (10.5, 2.0, 9.0, 2.0); CA_EXTERN NSString * const kCAMediaTimingFunctionDefault CA_AVAILABLE_STARTING (10.6, 3.0, 9.0, 2.0); */ @property (strong, nonatomic) CAMediaTimingFunction *timingFunction; @end 

POPBasicAnimation 提供的四种 TimingFunction

  • kCAMediaTimingFunctionLinear
img_fd82567a41c4c85e4526908bd66d4130.png
kCAMediaTimingFunctionLinear
  • kCAMediaTimingFunctionEaseIn
img_fd8a063944d32f4ec4bfcbb443db5086.png
kCAMediaTimingFunctionEaseIn
  • kCAMediaTimingFunctionEaseOut
img_81e20c400c89d9c173229ceb10424c0c.png
kCAMediaTimingFunctionEaseOut
  • kCAMediaTimingFunctionEaseInEaseOut
img_1f5a575ce63a0b462333d276b0cd830e.png
kCAMediaTimingFunctionEaseInEaseOut

示例

POPBasicAnimation * butAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter]; butAnimation.duration = 1.0f; butAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(_btn.centerX,_btn.centerY + 400)]; [_btn pop_addAnimation:butAnimation forKey:@"btn_Animation"]; 

弹性动画类 POPSpringAnimation

#import <pop/POPPropertyAnimation.h> /** 弹簧动画类;通过弹簧动力学模型实现动画 */ @interface POPSpringAnimation : POPPropertyAnimation /** 初始化一个实例 */ + (instancetype)animation; /** 指定属性动画的实例 */ + (instancetype)animationWithPropertyNamed:(NSString *)name; /** 当前速度; 做动画开始之前应该设置初始速度; */ @property (copy, nonatomic) id velocity; /** 反弹力度 范围 [0, 20],默认 4. */ @property (assign, nonatomic) CGFloat springBounciness; /** 速度 范围 [0, 20]. 默认 to 12. */ @property (assign, nonatomic) CGFloat springSpeed; /** 拉力 影响回弹力度以及速度 值越大,动画速度越快 */ @property (assign, nonatomic) CGFloat dynamicsTension; /** 摩擦力 如果开启,动画会不断重复,幅度逐渐削弱,直到停止。 */ @property (assign, nonatomic) CGFloat dynamicsFriction; /** 质量 细微的影响动画的回弹力度以及速度 */ @property (assign, nonatomic) CGFloat dynamicsMass; @end 
  • 胡克定义

F=-k·x
表达式为 F=-k·x 或 F=-k·Δx ,弹簧的弹力F和弹簧的伸长量(或压缩量)x 成正比,即 F= k·x 。k 是物质的弹性系数,它只由材料的性质所决定,与其他因素无关。负号表示弹簧所产生的弹力与其伸长(或压缩)的方向相反。

img_c1064f7250a977ae40af1bbb084efba8.png
Spring
img_463a3be2686525cf87ee65fc1f2ab423.png
DECAY

示例

POPSpringAnimation *springAnimaiton = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY]; springAnimaiton.toValue = @(500); [_btn pop_addAnimation:springAnimaiton forKey:@"springAnimation"]; springAnimaiton.springBounciness = 20; springAnimaiton.springSpeed = 20; 

以下这 3 个比较难用;如果不是特别需求,springBounciness 和 springSpeed 就可以解决问题;

// springAnimaiton.dynamicsTension = _value1; // springAnimaiton.dynamicsFriction = _value2; // springAnimaiton.dynamicsMass = _value3; 

衰减动画类 POPDecayAnimation

#import <pop/POPPropertyAnimation.h> /** 衰减动画,也有称阻尼动画 */ @interface POPDecayAnimation : POPPropertyAnimation /** 实例对象 */ + (instancetype)animation; /** 指定属性动画的实例 */ + (instancetype)animationWithPropertyNamed:(NSString *)name; /** 初始速度; 支持: kPOPValuePoint, kPOPValueInteger, kPOPValueFloat, kPOPValueRect, kPOPValueSize; */ @property (copy, nonatomic) id velocity; /** 原始速度 用于设置 autoreverse 和 repeatCount */ @property (copy, nonatomic, readonly) id originalVelocity; /** 减速:较低的值会更快的减速 范围[0, 1]. 默认 0.998. */ @property (assign, nonatomic) CGFloat deceleration; /** 预计持续时间; 根据 velocity 和 deceleration 得出 */ @property (readonly, assign, nonatomic) CFTimeInterval duration; /** 基于Velocity 和 deceleration; */ - (void)setToValue:(id)toValue NS_UNAVAILABLE; /** 反转速度 */ - (id)reversedVelocity; @end 

示例

POPDecayAnimation *anim = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPositionY]; anim.velocity = @(300); [_btn pop_addAnimation:anim forKey:@"slide"]; 

自定义动画 POPCustomAnimation

#import <pop/POPAnimation.h> @class POPCustomAnimation; /** 是自定义动画的回调块 每个帧动画回调此 block,最新的属性; target:动画对象,避免循环; animation:动画实例,确定上次回调来的当前时间,和已经使用的时间;避免循环使用; return no = 动画完成; */ typedef BOOL (^POPCustomAnimationBlock)(id target, POPCustomAnimation *animation); /** 自定义动画 */ @interface POPCustomAnimation : POPAnimation /** 初始化,并返回一个动画实例 */ + (instancetype)animationWithBlock:(POPCustomAnimationBlock)block; /** 当前动画的时间 */ @property (readonly, nonatomic) CFTimeInterval currentTime; /** 上次回调的时间 */ @property (readonly, nonatomic) CFTimeInterval elapsedTime; @end 

自定义属性动画 POPAnimatableProperty

#import <CoreGraphics/CoreGraphics.h> #import <Foundation/NSObject.h> @class POPMutableAnimatableProperty; /** 描述动画属性 */ @interface POPAnimatableProperty : NSObject <NSCopying, NSMutableCopying> /** 根据名字创建动画属性,名字不存在 = nil; */ + (id)propertyWithName:(NSString *)name; /** 根据名字创建动画属性,名字不存在 = nil; 如果名字存在,则初始化 block 实例; */ + (id)propertyWithName:(NSString *)name initializer:(void (^)(POPMutableAnimatableProperty *prop))block; /** 属性的名字,标识唯一动画属性 */ @property (readonly, nonatomic, copy) NSString *name; /** 返回当前属性值 */ @property (readonly, nonatomic, copy) void (^readBlock)(id obj, CGFloat values[]); /** 修改变化的值 */ @property (readonly, nonatomic, copy) void (^writeBlock)(id obj, const CGFloat values[]); /** 决定动画变化的间隔的阈(yu第四声)值;值越大,writeBlock 的调用次数越少; */ @property (readonly, nonatomic, assign) CGFloat threshold; @end /** 可变动画可变属性; */ @interface POPMutableAnimatableProperty : POPAnimatableProperty /** 属性的名称 */ @property (readwrite, nonatomic, copy) NSString *name; /** 返回当前属性值 */ @property (readwrite, nonatomic, copy) void (^readBlock)(id obj, CGFloat values[]); /** 修改变化的值 */ @property (readwrite, nonatomic, copy) void (^writeBlock)(id obj, const CGFloat values[]); /** 决定动画变化的间隔的阈(yu第四声)值;值越大,writeBlock的调用次数越少; */ @property (readwrite, nonatomic, assign) CGFloat threshold; @end /** 常见的 CALayer 属性名称 */ extern NSString * const kPOPLayerBackgroundColor; extern NSString * const kPOPLayerBounds; extern NSString * const kPOPLayerCornerRadius; extern NSString * const kPOPLayerBorderWidth; extern NSString * const kPOPLayerBorderColor; extern NSString * const kPOPLayerOpacity; extern NSString * const kPOPLayerPosition; extern NSString * const kPOPLayerPositionX; extern NSString * const kPOPLayerPositionY; extern NSString * const kPOPLayerRotation; extern NSString * const kPOPLayerRotationX; extern NSString * const kPOPLayerRotationY; extern NSString * const kPOPLayerScaleX; extern NSString * const kPOPLayerScaleXY; extern NSString * const kPOPLayerScaleY; extern NSString * const kPOPLayerSize; extern NSString * const kPOPLayerSubscaleXY; extern NSString * const kPOPLayerSubtranslationX; extern NSString * const kPOPLayerSubtranslationXY; extern NSString * const kPOPLayerSubtranslationY; extern NSString * const kPOPLayerSubtranslationZ; extern NSString * const kPOPLayerTranslationX; extern NSString * const kPOPLayerTranslationXY; extern NSString * const kPOPLayerTranslationY; extern NSString * const kPOPLayerTranslationZ; extern NSString * const kPOPLayerZPosition; extern NSString * const kPOPLayerShadowColor; extern NSString * const kPOPLayerShadowOffset; extern NSString * const kPOPLayerShadowOpacity; extern NSString * const kPOPLayerShadowRadius; /** 常见的 CAShapeLayer 属性名称 */ extern NSString * const kPOPShapeLayerStrokeStart; extern NSString * const kPOPShapeLayerStrokeEnd; extern NSString * const kPOPShapeLayerStrokeColor; extern NSString * const kPOPShapeLayerFillColor; /** 常见的 NSLayoutConstraint 属性名称 */ extern NSString * const kPOPLayoutConstraintConstant; #if TARGET_OS_IPHONE /** 常见的 UIView 属性名称 */ extern NSString * const kPOPViewAlpha; extern NSString * const kPOPViewBackgroundColor; extern NSString * const kPOPViewBounds; extern NSString * const kPOPViewCenter; extern NSString * const kPOPViewFrame; extern NSString * const kPOPViewScaleX; extern NSString * const kPOPViewScaleXY; extern NSString * const kPOPViewScaleY; extern NSString * const kPOPViewSize; extern NSString * const kPOPViewTintColor; /** 常见的 UIScrollView 属性名称 */ extern NSString * const kPOPScrollViewContentOffset; extern NSString * const kPOPScrollViewContentSize; extern NSString * const kPOPScrollViewZoomScale; extern NSString * const kPOPScrollViewContentInset; /** 常见的 UITableView 属性名称 */ extern NSString * const kPOPTableViewContentOffset; extern NSString * const kPOPTableViewContentSize; /** 常见的 UICollectionView 属性名称 */ extern NSString * const kPOPCollectionViewContentOffset; extern NSString * const kPOPCollectionViewContentSize; /** 常见的 UINavigationBar 属性名称 */ extern NSString * const kPOPNavigationBarBarTintColor; /** 常见的 UIToolbar 属性名称 */ extern NSString * const kPOPToolbarBarTintColor; /** 常见的 UITabBar 属性名称 */ extern NSString * const kPOPTabBarBarTintColor; /** 常见的 UILabel 属性名称 */ extern NSString * const kPOPLabelTextColor; 

自定义属性动画 POPPropertyAnimation

#import <pop/POPAnimatableProperty.h> #import <pop/POPAnimation.h> /** @abstract Flags for clamping animation values. @discussion Animation values can optionally be clamped to avoid overshoot. kPOPAnimationClampStart ensures values are more than fromValue and kPOPAnimationClampEnd ensures values are less than toValue. */ typedef NS_OPTIONS(NSUInteger, POPAnimationClampFlags) { kPOPAnimationClampNone = 0, kPOPAnimationClampStart = 1UL << 0, kPOPAnimationClampEnd = 1UL << 1, kPOPAnimationClampBoth = kPOPAnimationClampStart | kPOPAnimationClampEnd, }; /** semi-concrete 属性动画子类 */ @interface POPPropertyAnimation : POPAnimation /** 做动画的属性 */ @property (strong, nonatomic) POPAnimatableProperty *property; /** 做动画的初始值; 如果未设置,则在动画启动的时候,按照对象当前的值作为初始值; */ @property (copy, nonatomic) id fromValue; /** 做动画的值 如果未设置,则在动画启动的时候,按照对象当前的值作为初始值; */ @property (copy, nonatomic) id toValue; /** 四舍五入系数; 作用让动画变得更圆滑; 默认0; 取1.0和取整值之间; */ @property (assign, nonatomic) CGFloat roundingFactor; /** 就是让动画保证在fromValue和tovalue之间,不会越界; */ @property (assign, nonatomic) NSUInteger clampMode; /** 动画的值是叠加,而不是设置; 默认 NO; */ @property (assign, nonatomic, getter = isAdditive) BOOL additive; @end 

值得关注的 POP 周边

POP-HandApp 包含了大量动画的操作方法和上述介绍的实例。

AGGeometryKit-POP 通过 POP 对图片进行变形操作,非常酷。

POP-MCAnimate POP 的一个封装,可以让你更方便的使用 POP。

Rebound POP 的 Android 部分实现,主要是 Spring 的效果,移植自 Facebook 的rebound-js。

5 Steps For Using Facebook Pop

五步使用 Facebook Pop

五步使用 Facebook Pop

Facebook Pop 动画框架详细解析

Facebook Pop 源码注释

从 CoreAnimation 到 POP

缓动函数速查表

iOS 核心动画高级技巧

最后

POP 是一个新的里程碑,通过 POP,动画的开发门槛大大降低,并且实现了丰富的属性操作,其倡导的可中断式动画交互会革命性也值得我们仔细研究体会,想必不久就会涌现大量富有活力的 App ,感谢 Facebook,感谢开源。 Long live Opensource


内容来自于 丶纳凉里脊串Cocoachina 的博客

原文链接:https://yq.aliyun.com/articles/663780
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章