iOS Facebook-Pop 动效库的使用教程(Swift版)

简介:

好久没更新文章了,今天讲的是Facebook出的一款动效库Facebook-Pop。(部分内容摘自互联网,文章最后附有demo地址,有什么不对的地方,欢迎大家指正出来,大神勿喷,嘿嘿)

Pop是一个动画引擎,用以扩展iOS、OSX的动画类型。相较于iOS、OSX中的基本动画效果,Pop扩展后支持弹簧动画效果与衰减动画效果,你可以用Pop动画引擎来构建出真实的物理交互效果。它的API与Core Animation的API非常类似,使用起来非常容易。Pop动画引擎已经经过了良好的测试,Facebook在 Paper 应用中进行了大量使用。
官方Git地址:https://github.com/facebook/pop

iOS原生的Core Animation框架只提供了linear, ease-in, ease-out和ease-in-ease-out等4种静态动画:

而Pop在Core Animation基础上增加Spring、Decay和Custom 3种动态动画效果:

Spring(弹性)和Decay(衰减)可以让动画变得更灵动,而Custom这更为强大,可以给任何NSObject对象属性添加动画效果(待会有例子介绍)。

所以今天主要讲的就是4个动画效果

  • POPBasicAnimation //基础动画
  • POPSpringAnimation //弹性动画
  • POPDecayAnimation //衰减动画
  • POPCustomAnimation //自定义动画
使用

POPBasicAnimation

  • POPBasicAnimation使用最广泛 提供固定时间间隔的动画(如淡入淡出效果)
    let animation = POPBasicAnimation(propertyNamed: kPOPLayerPositionX)
    animation.toValue = NSValue(CGPoint: CGPointMake(100, 200))
    animation.duration = 2
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
    view.layer.pop_addAnimation(animation, forKey: "positionX")
    其实只有3个步骤就能创建一个动画

1.创建对应的动画类型,这里我使用的是kPOPLayerPositionX来控制view的位置
2.设置动画的属性
toValue设置动画的最终值(对应的还有fromValue是设置动画的起始值,不写默认为当前值)
duration设置动画时长
timingFunction是系统预设的动画类型有以下5种:

1
2
3
4
5
kCAMediaTimingFunctionLinear            线性,即匀速
kCAMediaTimingFunctionEaseIn 先慢后快
kCAMediaTimingFunctionEaseOut 先快后慢
kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
kCAMediaTimingFunctionDefault 实际效果是动画中间比较快

这里使用的是EaseIn(先慢后快)
3.最后只需把动画add到对应视图的layer就完成,设置了key可以方便删除和修改动画,例如:
[layer pop_removeAnimationForKey:@”positionX”];

POPSpringAnimation

  • POPSpringAnimation也许是大多数人使用POP的理由 其提供一个类似弹簧一般的动画效果(炫酷!)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    let animation = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
    animation!.toValue = NSValue(CGSize: CGSizeMake(5, 5))
    animation!.springBounciness = 10 //[0-20] 弹力 越大则震动幅度越大
    animation!.springSpeed = 20 //[0-20] 速度 越大则动画结束越快
    //以下3个与物理力学模拟相关,没特殊需求不建议使用
    // animation.dynamicsFriction = 0 //拉力
    // animation.dynamicsFriction = 0 //摩擦
    // animation.dynamicsMass = 0 //质量
    view.layer.pop_addAnimation(animation, forKey: "scaleXY")

POPSpringAnimation是没有duration字段的 其动画持续时间由以上几个参数决定,简单的几个步骤就能实现非常炫酷灵动的效果了

POPDecayAnimation

  • POPDecayAnimation提供一个过阻尼效果(其实Spring是一种欠阻尼效果) 可以实现类似UIScrollView的滑动衰减效果(是的 你可以靠它来自己实现一个UIScrollView)
    1
    2
    3
    4
    5
    6
    7
    8
    let animation = POPDecayAnimation(propertyNamed: kPOPLayerPositionX)

    animation.velocity = 200 //速度
    animation.deceleration = 0.998 // 衰减系数(越小则衰减得越快)

    //目的状态toValue是通过velocity和deceleration计算,动态得到

    view.layer.pop_addAnimation(animation, forKey: "decayPosition")

这是一个很简单的移动例子,当然强大的POP不止这些属性,在POPAnimatableProperty文件中还有很多可操作的属性,并且维护者还在不断增加:

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
/**
Common CALayer property names.
*/
public let kPOPLayerBackgroundColor: String
public let kPOPLayerBounds: String
public let kPOPLayerCornerRadius: String
public let kPOPLayerBorderWidth: String
public let kPOPLayerBorderColor: String
public let kPOPLayerOpacity: String
public let kPOPLayerPosition: String
public let kPOPLayerPositionX: String
public let kPOPLayerPositionY: String
public let kPOPLayerRotation: String
public let kPOPLayerRotationX: String
public let kPOPLayerRotationY: String
public let kPOPLayerScaleX: String
public let kPOPLayerScaleXY: String
public let kPOPLayerScaleY: String
public let kPOPLayerSize: String
public let kPOPLayerSubscaleXY: String
public let kPOPLayerSubtranslationX: String
public let kPOPLayerSubtranslationXY: String
public let kPOPLayerSubtranslationY: String
public let kPOPLayerSubtranslationZ: String
public let kPOPLayerTranslationX: String
public let kPOPLayerTranslationXY: String
public let kPOPLayerTranslationY: String
public let kPOPLayerTranslationZ: String
public let kPOPLayerZPosition: String
public let kPOPLayerShadowColor: String
public let kPOPLayerShadowOffset: String
public let kPOPLayerShadowOpacity: String
public let kPOPLayerShadowRadius: String
/**
Common CAShapeLayer property names.
*/
public let kPOPShapeLayerStrokeStart: String
public let kPOPShapeLayerStrokeEnd: String
public let kPOPShapeLayerStrokeColor: String
public let kPOPShapeLayerFillColor: String
public let kPOPShapeLayerLineWidth: String
public let kPOPShapeLayerLineDashPhase: String
/**
Common NSLayoutConstraint property names.
*/
public let kPOPLayoutConstraintConstant: String
/**
Common UIView property names.
*/
public let kPOPViewAlpha: String
public let kPOPViewBackgroundColor: String
public let kPOPViewBounds: String
public let kPOPViewCenter: String
public let kPOPViewFrame: String
public let kPOPViewScaleX: String
public let kPOPViewScaleXY: String
public let kPOPViewScaleY: String
public let kPOPViewSize: String
public let kPOPViewTintColor: String
/**
Common UIScrollView property names.
*/
public let kPOPScrollViewContentOffset: String
public let kPOPScrollViewContentSize: String
public let kPOPScrollViewZoomScale: String
public let kPOPScrollViewContentInset: String
public let kPOPScrollViewScrollIndicatorInsets: String
/**
Common UITableView property names.
*/
public let kPOPTableViewContentOffset: String
public let kPOPTableViewContentSize: String
/**
Common UICollectionView property names.
*/
public let kPOPCollectionViewContentOffset: String
public let kPOPCollectionViewContentSize: String
/**
Common UINavigationBar property names.
*/
public let kPOPNavigationBarBarTintColor: String
/**
Common UIToolbar property names.
*/
public let kPOPToolbarBarTintColor: String
/**
Common UITabBar property names.
*/
public let kPOPTabBarBarTintColor: String
/**
Common UILabel property names.
*/
public let kPOPLabelTextColor: String

什么?你说这里面没有你需要的,别着急POP还有更强大的自定义属性功能

自定义属性

  • POP默认支持的三种动画都继承自POPPropertyAnimation POPPropertyAnimation中定义了一个叫property的属性( 之前没有用到它是因为POP根据不同的默认动画属性帮你生成了默认的property) 而这个property则是用来驱动POP的动画效果中的重要一环
    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
testLabel = UILabel(frame: CGRectMake(0,0,100,50))
testLabel.center = view.center
view.addSubview(testLabel!)

let prop = POPAnimatableProperty.propertyWithName("Custom") { (prop) in
prop.writeBlock = {(obj, value) -> Void in
let lable = obj as! UILabel
lable.text = String.init(format: "%02d:%02d:%02d", Int(value[0]/60),Int(value[0]%60),Int((value[0]*100)%100))
}
}
let anBasic = POPBasicAnimation.linearAnimation()
anBasic.property = prop as! POPAnimatableProperty
anBasic.fromValue = 0
anBasic.toValue = 3*60
anBasic.duration = 3*60
testLabel!.pop_addAnimation(anBasic, forKey: "Custom")

效果如下:

从这个例子中有没有新的启发呢,POP可以做的事情远比CoreAnimation要多,它的强大毋庸置疑。


Demo地址:https://github.com/yueyeqi/Facebook-PopExample


小结

其实只需要熟练掌握POP自带的三种动画 即可完成大部分的动画效果 如果实在是无法满足你的需求的话 自定义动画也基本可以满足你的要求 可以说POP化繁为简的出现 极大的方便了我们这些苦逼的coder 本文主要只介绍了最基本的使用方法和思路,更多的知识和效果还待大家深入了解 完。