POP介绍与使用实践(快速上手动画)
http://www.cocoachina.com/ios/20150728/12734.html
作者:里脊串 授权本站转载。
前言
动画在APP开发过程中,大家多多少少都会接触到,而且随着iOS7的扁平化风格启用之后,越来越多的APP开始尝试加入各种绚丽的动画交互效果以增加APP的用户体验。(当然,还是以国外的APP居多)
有过相关开发经验的同学肯定知道在iOS中,动画相关的部分都是基于Core Animation,但是今天我们不讨论Core Animation。今天的主角是POP -来自于Facebook的动画引擎(其实我不喜欢把POP定义为动画引擎 我愿意称它为函数发生器)
介绍
官方地址 https://github.com/facebook/pop
官方介绍(翻译版)
POP是一个在iOS与OS X上通用的极具扩展性的动画引擎。它在基本的静态动画的基础上增加的弹簧动画与衰减动画,使之能创造出更真实更具物理性的交互动画。POP的API可以快速的与现有的ObjC代码集成并可以作用于任意对象的任意属性。
POP是个相当成熟且久经考验的框架,Facebook出品的令人惊叹的Paper应用中的所有动画和效果即出自POP。
安装方式还是推荐使用CocoaPod。
1 | pod 'pop' , '~> 1.0' |
POP的神奇之处在于,它是独立与Core Animation的存在。所以,忘记Core Animation吧,忘记Layer Tree吧,迎接一个简单的明天!(LOL 开玩笑的~:) 很多地方还是会需要Core Animation的,不过说不定哪天苹果大发善心,将动画相关的部分向POP借鉴一点也不是不可能的(比如SpriteKit就借鉴了Cocos2D :)
使用
POP默认支持三种动画,但同时也支持自定义动画。
-
POPBasicAnimation
-
POPSpringAnimation
-
POPDecayAnimation
-
POPCustomAnimation //自定义动画
这里我们只讨论前三种(因为自定义动画我也没用过 :) 先来看看官方的示例代码吧。
官方代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 | //Basic animations can be used to interpolate values over a specified time period. To use an ease-in ease-out animation to animate a view's alpha from 0.0 to 1.0 over the default duration: POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewAlpha]; anim.fromValue = @(0.0); anim.toValue = @(1.0); [view pop_addAnimation:anim forKey:@ "fade" ]; //Spring animations can be used to give objects a delightful bounce. In this example, we use a spring animation to animate a layer's bounds from its current value to (0, 0, 400, 400): POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds]; anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 400, 400)]; [layer pop_addAnimation:anim forKey:@ "size" ]; //Decay animations can be used to gradually slow an object to a halt. In this example, we decay a layer's positionX from it's current value and velocity 1000pts per second: POPDecayAnimation *anim = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPositionX]; anim.velocity = @(1000.); [layer pop_addAnimation:anim forKey:@ "slide" ]; |
POPBasicAnimation
POPBasicAnimation使用最广泛 提供固定时间间隔的动画(如淡入淡出效果)
代码示例1
1 2 3 4 | POPBasicAnimation *anBasic = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionX]; anBasic.toValue = @(self.square.center.y+300); anBasic.beginTime = CACurrentMediaTime() + 1.0f; [self.square pop_addAnimation:anBasic forKey:@ "position" ]; |
其动画效果如下
可以看到,添加一个动画最少仅需三步
-
定义一个animation对象,并指定对应的动画属性
-
设置初始值和默认值(初始值可以不指定,会默认从当前值开始)
-
添加到想产生动画的对象上
POPBasicAnimation可配置的属性与默认值为
1 | duration:0.4 //动画间隔 |
POPBasicAnimation提供四种timingfunction(很熟悉,对不对? 就是Core Animation中那些)
-
kCAMediaTimingFunctionLinear
-
kCAMediaTimingFunctionEaseIn
-
kCAMediaTimingFunctionEaseOut
-
kCAMediaTimingFunctionEaseInEaseOut
其时间函数分别如下
POPSpringAnimation
POPSpringAnimation也许是大多数人使用POP的理由,其提供一个类似弹簧一般的动画效果(使用后,APP立马就活泼起来了,有木有?!)
代码示例23
1 2 3 4 5 | POPSpringAnimation *anSpring = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionX]; anSpring.toValue = @(self.square.center.y+300); anSpring.beginTime = CACurrentMediaTime() + 1.0f; anSpring.springBounciness = 10.0f; [self.square pop_addAnimation:anSpring forKey:@ "position" ]; |
其动画效果如下
POPSpringAnimation可配置的属性与默认值为
1 2 3 4 5 | springBounciness:4.0 //[0-20] 弹力 越大则震动幅度越大 springSpeed :12.0 //[0-20] 速度 越大则动画结束越快 dynamicsTension :0 //拉力 接下来这三个都跟物理力学模拟相关 数值调整起来也很费时 没事不建议使用哈 dynamicsFriction:0 //摩擦 同上 dynamicsMass :0 //质量 同上 |
注意:POPSpringAnimation是没有duration字段的,其动画持续时间由以上几个参数决定
其时间函数如下
POPDecayAnimation
POPDecayAnimation提供一个过阻尼效果(其实Spring是一种欠阻尼效果),可以实现类似UIScrollView的滑动衰减效果(是的 你可以靠它来自己实现一个UIScrollView)
代码示例3
1 2 3 4 | POPDecayAnimation *anDecay = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPositionX]; anDecay.velocity = @(600); anDecay.beginTime = CACurrentMediaTime() + 1.0f; [self.square pop_addAnimation:anDecay forKey:@ "position" ]; |
其动画效果如下
注意:这里对POPDecayAnimation设置toValue是没有意义的,会被忽略(因为目的状态是动态计算得到的)
POPDecayAnimation可配置的属性与默认值为
1 | deceleration:0.998 //衰减系数(越小则衰减得越快) |
注意:POPDecayAnimation也是没有duration字段的,其动画持续时间由velocity与deceleration决定
其时间函数如下
接下来我们看一下POP默认支持哪些属性的动画。打开POPAnimatablePropery.h可以看到如下定义(这些是到目前为止 所支持的属性 随着版本的更新 还在不断的新增中 :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /** Common CALayer property names. */ 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; /** Common CAShapeLayer property names. */ extern NSString * const kPOPShapeLayerStrokeStart; extern NSString * const kPOPShapeLayerStrokeEnd; extern NSString * const kPOPShapeLayerStrokeColor; extern NSString * const kPOPShapeLayerFillColor; /** Common NSLayoutConstraint property names. */ extern NSString * const kPOPLayoutConstraintConstant; #if TARGET_OS_IPHONE /** Common UIView property names. */ 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; /** Common UIScrollView property names. */ extern NSString * const kPOPScrollViewContentOffset; extern NSString * const kPOPScrollViewContentSize; extern NSString * const kPOPScrollViewZoomScale; extern NSString * const kPOPScrollViewContentInset; /** Common UITableView property names. */ extern NSString * const kPOPTableViewContentOffset; extern NSString * const kPOPTableViewContentSize; /** Common UICollectionView property names. */ extern NSString * const kPOPCollectionViewContentOffset; extern NSString * const kPOPCollectionViewContentSize; /** Common UINavigationBar property names. */ extern NSString * const kPOPNavigationBarBarTintColor; /** Common UIToolbar property names. */ extern NSString * const kPOPToolbarBarTintColor; /** Common UITabBar property names. */ extern NSString * const kPOPTabBarBarTintColor; /** Common UILabel property names. */ extern NSString * const kPOPLabelTextColor; |
作为刚接触POP的一些同学来说,如果在上面看到你希望的某些属性的话,你可以像官方代码示例一样指定这个属性即可开始动画了
但是如果你想要的某些属性不在之上呢,这时候自定义属性POPAnimatableProperty就排上用场了
自定义属性
POP默认支持的三种动画都继承自POPPropertyAnimation。POPPropertyAnimation中定义了一个叫property的属性( 之前没有用到它是因为POP根据不同的默认动画属性帮你生成了默认的property) 而这个property则是用来驱动POP的动画效果中的重要一环。
代码示例4
1 2 3 4 5 6 7 8 9 10 | POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:@ "prop" initializer:^(POPMutableAnimatableProperty *prop) { // read value prop.readBlock = ^(id obj, CGFloat values[]) { }; // write value prop.writeBlock = ^(id obj, const CGFloat values[]) { }; // dynamics threshold prop.threshold = 0.01; }]; |
其组成就是一个readBlock一个writeBlock和一个threashold
-
readBlock告诉POP当前的属性值
-
writeBlock中修改变化后的属性值
-
threashold决定了动画变化间隔的阈值,值越大writeBlock的调用次数越少
POPAnimatableProperty其实是POP中一个比较重要的东西,像上面提到的POP自带的动画属性,查看源代码可以看到也只是POP自动帮你设置好了POPAnimatableProperty而已,其作用就是当动画的某个时间片被触发时,告诉系统如何根据当前时间片做出变化。
还是以一个实际的例子来说明如何使用自定义属性,比如我们要实现一个像系统的时钟APP里秒表计时的一个效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:@ "countdown" initializer:^(POPMutableAnimatableProperty *prop) { prop.writeBlock = ^(id obj, const CGFloat values[]) { UILabel *lable = (UILabel*)obj; label.text = [NSString stringWithFormat:@ "d:d:d" ,(int)values[0]/60,(int)values[0]%60,(int)(values[0]*100)0]; }; // prop.threshold = 0.01f; }]; POPBasicAnimation *anBasic = [POPBasicAnimation linearAnimation]; //秒表当然必须是线性的时间函数 anBasic.property = prop; //自定义属性 anBasic.fromValue = @(0); //从0开始 anBasic.toValue = @(3*60); //180秒 anBasic.duration = 3*60; //持续3分钟 anBasic.beginTime = CACurrentMediaTime() + 1.0f; //延迟1秒开始 [label pop_addAnimation:anBasic forKey:@ "countdown" ]; |
其动画效果如下
有没有从中得到一些启发呢? POP可以做的事情可远比Core Animation要多(注意这里我们使用了beginTime这个属性来设置动画的延迟施放) 例如音乐播放时那种淡入淡出的效果等等也可以用POP来实现
小结
其实只需要熟练掌握POP自带的三种动画,即可完成大部分的动画效果。如果实在是无法满足你的需求的话,自定义动画也基本可以满足你的要求。可以说POP化繁为简的出现,极大的方便了我们这些苦逼的coder。
当然,就像我说的,POP不仅仅是一个动画引擎。相信经过我最后一个例子,大家可以得到一点启示,POP能做的事情还不少 :)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具