背景
- 最近公司有了一個創新項目,就是在視頻視圖之上添加一層視圖,視圖設計涉及到了復雜的控件動畫,會根據視頻的播放,顯示一些控件,控件有位移、縮放、旋轉、shake等動畫。
- 在網上調研了一下,對比了蘋果的CoreAnimation,覺得Facebook_Pop使用起來更加簡單一些,并且有很多優點。
- 在使用中,遇到了一個bug,Pop的kPOPLayerRotationY存在Bug,大于90度就會出錯。
Pop介紹
-
Pop的Github
-
Facebook 在發布了 Paper 之后,似乎還不滿足于只是將其作為一個概念性產品,更進一步開源了其背后的動畫引擎 POP,此舉大有三年前發布的 iOS UI 框架 Three20 的意味。而 POP 開源后也不負 Facebook 的厚望。
-
POP背后的開發者是 Kimon Tsinteris, Push Pop Press 的聯合創始人,曾經在Apple擔任高級工程師,并參與了 iPhone 和 iPad 上軟件的研發(iPhone的指南針以及地圖)。2011年的時候 Facebook 收購了他的公司,此后他便加入了 Facebook 負責 Facebook iOS 版本的開發。
-
如果你打開 Push Pop Press 開發的 AI Gore 這款 App,你會發現交互和動畫與Paper幾乎如出一轍。對,他們都是 Kimon Tsinteris 開發的。
-
不滿于 Apple 自身動畫框架的單調,Push Pop Press 致力于創造一個逼真的、充滿物理效應的體驗。 POP 就是這個理念下最新一代的成果。
-
POP 使用 Objective-C++ 編寫,Objective-C++ 是對 C++ 的擴展,就像 Objective-C 是 C 的擴展。而至于為什么他們用 Objective-C++ 而不是純粹的 Objective-C,原因是他們更喜歡 Objective-C++ 的語法特性所提供的便利。
繼承關系
POPAnimation
// 動畫名稱
@property (copy, nonatomic) NSString *name;
// 開始時間,默認立即開始
@property (assign, nonatomic) CFTimeInterval beginTime;// 代理
@property (weak, nonatomic) id delegate;// 事件追蹤
@property (readonly, nonatomic) POPAnimationTracer *tracer;// 開始的block
@property (copy, nonatomic) void (^animationDidStartBlock)(POPAnimation *anim);// 動畫觸發toValue值的block
@property (copy, nonatomic) void (^animationDidReachToValueBlock)(POPAnimation *anim);// 動畫完成的回調
@property (copy, nonatomic) void (^completionBlock)(POPAnimation *anim, BOOL finished);// 動畫每一幀的回調
@property (copy, nonatomic) void (^animationDidApplyBlock)(POPAnimation *anim);// 動畫是否在結束后移除,默認為YES
@property (assign, nonatomic) BOOL removedOnCompletion;// 暫停
@property (assign, nonatomic, getter = isPaused) BOOL paused;// 動畫是否返回原來的狀態,以動畫形式返回
@property (assign, nonatomic) BOOL autoreverses;// 重復次數
@property (assign, nonatomic) NSInteger repeatCount;// 是都永遠重復
@property (assign, nonatomic) BOOL repeatForever;
POPPropertyAnimation
// 動畫的屬性,我們可以借助此屬性,做一些自定義
@property (strong, nonatomic) POPAnimatableProperty *property;// 動畫開始的值
@property (copy, nonatomic) id fromValue;// 動畫結束的值
@property (copy, nonatomic) id toValue;// 動畫的細膩度,設置很大的值會有bug 【0,1】
@property (assign, nonatomic) CGFloat roundingFactor;// 沒理解
@property (assign, nonatomic) NSUInteger clampMode;// 沒理解
@property (assign, nonatomic, getter = isAdditive) BOOL additive;
POPBaseAnimation
+ (instancetype)animationWithPropertyNamed:(NSString *)name;
// 線性的
kCAMediaTimingFunctionLinear
// 慢->快
kCAMediaTimingFunctionEaseIn
// 快->慢
kCAMediaTimingFunctionEaseOut
// 慢->快->慢
kCAMediaTimingFunctionEaseInEaseOut
POPBasicAnimation *baseAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
baseAnim.completionBlock = ^(POPAnimation *anim, BOOL finished) {NSLog(@"動畫完成”);
};baseAnim.duration = 0.5;
baseAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
baseAnim.fromValue = @(self.demoView.center);
baseAnim.toValue = @(self.view.center);
[self.demoView pop_addAnimation:baseAnim forKey:@"baseAnim”];
POPAnimatableProperty *prop = [POPAnimatableProperty propertyWithName:@"countdown" initializer:^(POPMutableAnimatableProperty *prop) {prop.writeBlock = ^(id obj, const CGFloat *values) {NSLog(@"%d", (int)values[0]);int value = (int)values[0];NSString *timeStr = [NSString stringWithFormat:@"%02d:%02d:%02d", value/60, value%60,(int)(values[0]*100)%100];self.label.text = timeStr;};
}];POPBasicAnimation *anBasic = [POPBasicAnimation linearAnimation]; //秒表當然必須是線性的時間函數
anBasic.property = prop; //自定義屬性
anBasic.fromValue = @(1*60); //從0開始
anBasic.toValue = @(0); //180秒
anBasic.duration = 3*60; //持續3分鐘
anBasic.beginTime = CACurrentMediaTime(); //延遲1秒開始
[self.label pop_addAnimation:anBasic forKey:@"countdown”];
POPSpringAnimation
+ (instancetype)animationWithPropertyNamed:(NSString *)name;
// 初始速度
@property (copy, nonatomic) id velocity;// 彈力 [0,20],默認為4
@property (assign, nonatomic) CGFloat springBounciness;// 彈簧速度 [0,20],默認為12
@property (assign, nonatomic) CGFloat springSpeed;// 拉力,張力
@property (assign, nonatomic) CGFloat dynamicsTension;// 摩擦力
@property (assign, nonatomic) CGFloat dynamicsFriction;// 質量
@property (assign, nonatomic) CGFloat dynamicsMass;
POPSpringAnimation *anSpr = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
anSpr.completionBlock = ^(POPAnimation *anim, BOOL finished) {NSLog(@"動畫完成”);
};
anSpr.springSpeed = 100;
anSpr.springBounciness = 20.0;
anSpr.fromValue = @(self.demoView.center);
anSpr.toValue = @(self.view.center);
[self.demoView pop_addAnimation:anSpr forKey:@"anSpr”];
POPDecayAnimation
-
Decay Animation 就是 POP 提供的另外一個非常特別的動畫,他實現了一個衰減的效果。這個動畫有一個重要的參數 velocity(速率),一般并不用于物體的自發動畫,而是與用戶的交互共生。這個和 iOS7 引入的 UIDynamic 非常相似,如果你想實現一些物理效果,這個也是非常不錯的選擇。
-
Decay 的動畫沒有 toValue 只有 fromValue,然后按照 velocity 來做衰減操作。
-例子4:衰減轉動
- (void)jumpAnimation {[self.demoView.layer pop_removeAllAnimations];POPDecayAnimation *anRotaion=[POPDecayAnimation animation];anRotaion.property = [POPAnimatableProperty propertyWithName:kPOPLayerRotation];if (self.animated) {anRotaion.velocity = @(-150);}else{anRotaion.velocity = @(150);anRotaion.fromValue = @(25.0);}self.animated = !self.animated;anRotaion.completionBlock = ^(POPAnimation *anim, BOOL finished) {if (finished) {[self jumpAnimation];}};[self.demoView.layer pop_addAnimation:anRotaion forKey:@"myRotationView”];
}
值得關注的 POP 周邊
-
POP-HandApp 這就是本文的示例App,包含了大量動畫的操作方法和上述介紹的實例。
-
AGGeometryKit-POP 通過 POP 對圖片進行變形操作,非???。
-
POP-MCAnimate POP 的一個封裝,可以讓你更方便的使用 POP。
-
Rebound POP 的 Android 部分實現,主要是 Spring 的效果,移植自 Facebook 的rebound-js。
總結
以上是生活随笔為你收集整理的Facebook_Pop的使用指北的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。