POP介紹與使用實踐(快速上手動畫)[轉]

前言


動畫在APP開發過程當中 你們多多少少都會接觸到 並且隨着ios7的扁平化風格啓用以後 愈來愈多的APP開始嘗試加入各類絢麗的動畫交互效果以增長APP的用戶體驗(固然 仍是以國外的APP居多)ios

有過相關開發經驗的同窗確定知道在iOS中 動畫相關的部分都是基於Core Animation 可是今天咱們不討論Core Animation 今天的主角是POP -來自於Facebook的動畫引擎(其實我不喜歡把POP定義爲動畫引擎 我願意稱它爲函數發生器)git

介紹


官方地址 https://github.com/facebook/pop
官方介紹(翻譯版)github

POP是一個在iOS與OS X上通用的極具擴展性的動畫引擎 它在基本的靜態動畫的基礎上增長的彈簧動畫與衰減動畫 使之能創造出更真實更具物理性的交互動畫 POP的API能夠快速的與現有的ObjC代碼集成並能夠做用於任意對象的任意屬性
POP是個至關成熟且久經考驗的框架 Facebook出品的使人驚歎的Paper應用中的全部動畫和效果即出自POPspring

安裝方式仍是推薦使用CocoaPod框架

1
pod 'pop', '~> 1.0'

 

POP的神奇之處在於 它是獨立與Core Animation的存在 因此 忘記Core Animation吧 忘記Layer Tree吧 迎接一個簡單的明天 (LOL 開玩笑的~:) 不少地方仍是會須要Core Animation的 不過說不定哪天蘋果大發善心 將動畫相關的部分向POP借鑑一點也不是不可能的(好比SpriteKit就借鑑了Cocos2D :)ide

使用


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使用最普遍 提供固定時間間隔的動畫(如淡入淡出效果)ui

代碼示例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"];

其動畫效果以下
POPBasicAnimationPOPBasicAnimationthis

能夠看到 添加一個動畫最少僅需三步

  1. 定義一個animation對象 並指定對應的動畫屬性
  2. 設置初始值和默認值(初始值能夠不指定 會默認從當前值開始)
  3. 添加到想產生動畫的對象上

POPBasicAnimation可配置的屬性與默認值爲

1
duration:0.4 //動畫間隔

 

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

  • kCAMediaTimingFunctionLinear
  • kCAMediaTimingFunctionEaseIn
  • kCAMediaTimingFunctionEaseOut
  • kCAMediaTimingFunctionEaseInEaseOut

其時間函數分別以下

kCAMediaTimingFunctionLinearkCAMediaTimingFunctionLinear
kCAMediaTimingFunctionEaseInkCAMediaTimingFunctionEaseIn
kCAMediaTimingFunctionEaseOutkCAMediaTimingFunctionEaseOut
kCAMediaTimingFunctionEaseInEaseOutkCAMediaTimingFunctionEaseInEaseOut

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能作的事情還很多 :)

 

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

相關文章
相關標籤/搜索