http://adad184.com/2015/03/11/intro-to-pop/

前言


动画在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
14
15
16
//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"];

其动画效果如下
POPBasicAnimation

可以看到 添加一个动画最少仅需三步

  1. 定义一个animation对象 并指定对应的动画属性
  2. 设置初始值和默认值(初始值可以不指定 会默认从当前值开始)
  3. 添加到想产生动画的对象上

POPBasicAnimation可配置的属性与默认值为

1
duration:0.4    //动画间隔

POPBasicAnimation提供四种timingfunction(很熟悉 对不对? 就是Core Animation中那些)

  • kCAMediaTimingFunctionLinear
  • kCAMediaTimingFunctionEaseIn
  • kCAMediaTimingFunctionEaseOut
  • kCAMediaTimingFunctionEaseInEaseOut

其时间函数分别如下

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
92
93
94
95
96
97
98
99
100
101
102
103
/**
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
11
12
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
15
16
17
18
    POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:@"countdown" initializer:^(POPMutableAnimatableProperty *prop) {

        prop.writeBlock = ^(id obj, const CGFloat values[]) {
UILabel *lable = (UILabel*)obj;
label.text = [NSString stringWithFormat:@"%02d:%02d:%02d",(int)values[0]/60,(int)values[0]%60,(int)(values[0]*100)%100];
}; // 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能做的事情还不少 :)

POP介绍与使用实践(快速上手动画)的更多相关文章

  1. POP介绍与使用实践(快速上手动画)[转]

    前言 动画在APP开发过程中 大家多多少少都会接触到 而且随着ios7的扁平化风格启用之后 越来越多的APP开始尝试加入各种绚丽的动画交互效果以增加APP的用户体验(当然 还是以国外的APP居多) 有 ...

  2. [转载]Masonry介绍与使用实践(快速上手Autolayout)

    原博地址 http://adad184.com/2014/09/28/use-masonry-to-quick-solve-autolayout/ 前言 1 MagicNumber -> aut ...

  3. Masonry介绍与使用实践(快速上手Autolayout)

    MagicNumber -> autoresizingMask -> autolayout 以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时代 win ...

  4. 【转】Masonry介绍与使用实践(快速上手Autolayout)

    原文网址:http://adad184.com/2014/09/28/use-masonry-to-quick-solve-autolayout/ 前言 1 MagicNumber -> aut ...

  5. Masonry介绍与使用实践 - iOS移动开发周报

    本文转发至 http://www.tuicool.com/articles/MRbaEnB/ 原文  http://www.infoq.com/cn/news/2014/11/masonry-intr ...

  6. 几个小实践带你快速上手MindSpore

    摘要:本文将带大家通过几个小实践快速上手MindSpore,其中包括MindSpore端边云统一格式及华为智慧终端背后的黑科技. MindSpore介绍 MindSpore是一种适用于端边云场景的新型 ...

  7. 官方 React 快速上手脚手架 create-react-app

    此文简单讲解了官方 React 快速上手脚手架的安装与介绍. 1. React 快速上手脚手架 create-react-app 为了快速地进行构建使用 React 的项目,FaceBook 官方发布 ...

  8. 【学习总结】快速上手Linux玩转典型应用-第1章-课程介绍

    课程目录链接 快速上手Linux玩转典型应用-目录 1. Linux有什么用 2. 课程安排 3. 课程收获 基本运维能力,等等 END

  9. 【转】Vue.js 2.0 快速上手精华梳理

    Vue.js 2.0 快速上手精华梳理 Sandy 发掘代码技巧:公众号:daimajiqiao 自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新 ...

随机推荐

  1. 关于ie11的浏览器检测

    我的电脑昨天更新的时候把ie11给更新出来了,然后发现我的skylineweb项目提示我的浏览器不是ie,这样显然是浏览器检测出现了问题.查找后找到了下面的解决方法.大家的电脑如果也更新成了ie11的 ...

  2. PipeCAD 简介

    PipeCAD 简介 PipeCAD的定位是中小型项目的管道设计软件,主要有管道建模.设备建模以及管道ISO图及平面图功能.程序的操作方式尽量参考PDMS,考虑灵活性.易于使用.如果用来和国内其他管道 ...

  3. 【JZOJ5179】【NOI2017模拟6.29】哈哈

    题意 给定一个长度为n的序列,你可以进行若干次操作: 选择一个区间,删掉,并获得Val[Len]的得分,Len为这个区间的长度: 其中这个区间满足: 1.相邻两个数差的绝对值为1 2.每个数都大于相邻 ...

  4. 群晖的moments套件 发生未知错误

    一次了,哎 也不知道什么原因引起的 只能再搞一遍 先把homes文件夹数据弄走,免得弄丢 然后卸载momemts,删除数据库 还有其他人遇到这个情况http://www.gebi1.com/threa ...

  5. scrapy中的Request和Response对象

    前言: 如果框架中的组件比做成是人的各个器官的话,那个Request和Response就是血液,Item就是代谢产物 Request对象: 是用来描述一个HTTP请求,其构造参数有 url 请求的UR ...

  6. String、StringBuffer和StringBuilder源码解析

    1.String 1.1类的定义 public final class String implements java.io.Serializable, Comparable<String> ...

  7. Leetcode543.Diameter of Binary Tree二叉树的直径

    给定一棵二叉树,你需要计算它的直径长度.一棵二叉树的直径长度是任意两个结点路径长度中的最大值.这条路径可能穿过根结点. 示例 : 给定二叉树 1 / \ 2    3 / \ 4  5 返回 3, 它 ...

  8. 洛谷P3299 保护出题人

    注意每一关的时候,前一关的植物会消失.保留整数指四舍五入. 解:冷静分析一波,列一个式子出来,发现每一关的植物攻击力要是(ai + ... + aj) / (xi + d * (i - j))的最大值 ...

  9. npm常用命令及版本号

    npm 包管理器的常用命令 测试环境为node>=8.1.3&&npm>=5.0.3 1, 首先是安装命令 //全局安装 npm install 模块名 -g //本地安装 ...

  10. JS---案例:无刷新评论---属于创建对象的案例拿出来复习

    案例:无刷新评论---属于创建对象的案例拿出来复习 创建行和单元格,添加到相应元素中,设置内容 createElement, appendChild,innerHTML <!DOCTYPE ht ...