目錄
- ** UIView 動畫 **
- ** Core Animation **
- ** FaceBook POP動畫 **
在iOS中,圖形可分為以下幾個(gè)層次:

<p>OpenGL ES使用硬件加速接口來處理先進(jìn)的2d 和3d 呈現(xiàn)。OpenGLES通常由游戲開發(fā)者或想實(shí)現(xiàn)沉浸式圖像體驗(yàn)的開發(fā)者使用。OpenGLES框架提供對呈現(xiàn)過程的全部控制,以及提供創(chuàng)建平滑動畫所需要的幀速。</p>
- 創(chuàng)建2D和3D圖形
- 創(chuàng)建更復(fù)雜的圖形,比如數(shù)據(jù)虛擬化、模擬飛行,或者視頻游戲
- 訪問底層圖形設(shè)備
<p>Core Graphics也稱作Quartz,是對定制的2D向量和圖像呈現(xiàn)提供支持的本地繪制引擎。該框架提供的引擎雖然沒有OpenGLES引擎速度快,但該框架能夠很好地適合于呈現(xiàn)定制的2d圖形和動態(tài)圖像。</p>
- 創(chuàng)建基于路徑的繪圖
- 抗鋸齒渲染
- 添加梯度、圖片和顏色
- Use coordinate-space transformations.
- 創(chuàng)建、顯示和分析PDF文檔
<p>Core Animation也是Quartz核心框架的一部分,是優(yōu)化應(yīng)用動畫體驗(yàn)的基礎(chǔ)技術(shù)。使用Core Animation可以創(chuàng)建嵌套的對象,并且可以對它們操作、旋轉(zhuǎn)、縮放和轉(zhuǎn)換。使用Core animation,你可以創(chuàng)建動態(tài)的用戶界面而不用使用更底層的圖形API,如OpenGL ES。</p>
- 創(chuàng)建定制動畫
- 添加定時(shí)函數(shù)和圖形
- 支持幀動畫
- Specify graphical layout constraints.
- Group multiple-layer changes into anatomic update.
<p>UIKit視圖基于 Core Animation提供視圖級別的動畫支持。</p>
實(shí)現(xiàn)動畫三要素
- 元素(who)
- 行為(how)
- 執(zhí)行(do)
兩個(gè)概念
1.仿射變換(Affine Transformation或 Affine Map)
是一種二維坐標(biāo)到二維坐標(biāo)之間的線性變換,它保持了二維圖形的“平直性”(即:直線經(jīng)過變換之后依然是直線)和“平行性”(即:二維圖形之間的相對位置關(guān)系保持不變,平行線依然是平行線,且直線上點(diǎn)的位置順序不變)。
- 變換原理
<pre><code>struct CGAffineTransform {
CGFloat a;
CGFloat b;
CGFloat c;
CGFloat d;
CGFloat tx;
CGFloat ty;
};</code></pre>
結(jié)構(gòu)體矩陣圖為:(矩陣圖)

因?yàn)樽詈笠涣锌偸鞘?0,0,1),所以有用的信息就是前面兩列
對一個(gè)view進(jìn)行仿射變化就相當(dāng)于對view上的每個(gè)點(diǎn)做一個(gè)乘法
結(jié)果就是:(映射變換)

相當(dāng)于:
(x, y, 1 ) --> (ax + cy + tx, bx + dy + ty, 1)
如果不看c和b的話
a表示x水平方向的縮放,tx表示x水平方向的偏移
d表示y垂直方向的縮放,ty表示y垂直方向的偏移
如果b和c不為零的話,那么視圖肯定發(fā)生了旋轉(zhuǎn)
<p>仿射變換可以通過一系列的原子變換的復(fù)合來實(shí)現(xiàn),包括:平移(Translation)、縮放(Scale)、翻轉(zhuǎn)(Flip)、旋轉(zhuǎn)(Rotation)和錯(cuò)切(Shear)。
</p>
- 常用函數(shù)
<pre><code>/// 用來連接兩個(gè)變換效果并返回。返回的t = t1 * t2
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2)
/// 矩陣初始值。[ 1 0 0 1 0 0 ]
CGAffineTransformIdentity
/// 自定義矩陣變換,需要掌握矩陣變換的知識才知道怎么用。參照(x, y, 1 ) --> (ax + cy + tx, bx + dy + ty, 1)
CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)
/// 旋轉(zhuǎn)視圖。傳入?yún)?shù)為 角度 * (M_PI / 180)。等同于 CGAffineTransformRotate(self.transform, angle)
CGAffineTransformMakeRotation(CGFloat angle)
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
/// 縮放視圖。等同于CGAffineTransformScale(self.transform, sx, sy)
CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
/// 平移視圖。等同于CGAffineTransformTranslate(self.transform, tx, ty)
CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)
</code></pre>
2.貝塞爾曲線
是應(yīng)用于二維圖形應(yīng)用程序的數(shù)學(xué)曲線。
曲線定義:起始點(diǎn)、終止點(diǎn)(也稱錨點(diǎn))、控制點(diǎn)。
通過調(diào)整控制點(diǎn),貝塞爾曲線的形狀會發(fā)生變化。
- 線性貝塞爾曲線
由 P0 至 P1 的連續(xù)點(diǎn), 描述的一條線段
- 二次貝塞爾曲線
原理:
由 P0 至 P1 的連續(xù)點(diǎn) Q0,描述一條線段
由 P1 至 P2 的連續(xù)點(diǎn) Q1,描述一條線段。
由 Q0 至 Q1 的連續(xù)點(diǎn) B(t),描述一條二次貝塞爾曲線。
- 三次貝塞爾曲線
** 通用公式:**
** 高階貝塞爾曲線:**
- 四次貝塞爾曲線
- 五次貝塞爾曲線

貝塞爾曲線應(yīng)用在動畫中,描述物件的運(yùn)動路徑等等。
UIBezierPath
使用UIBezierPath類可以創(chuàng)建基于矢量的路徑,這個(gè)類在UIKit中。此類是Core Graphics框架關(guān)于CGPathRef的一個(gè)封裝。
path如果是基于矢量形狀的,都用直線和曲線段去創(chuàng)建。 我們使用直線段去創(chuàng)建矩形和多邊形,使用曲線段去創(chuàng)建?。╝rc),圓或者其他復(fù)雜的曲線形狀。 每一段都包括一個(gè)或者多個(gè)點(diǎn),繪圖命令定義如何去詮釋這些點(diǎn)。每一個(gè)直線段或者曲線段的結(jié)束的地方是下一個(gè)的開始的地方。每一個(gè)連接的直線或者曲線段的集合成為subpath。一個(gè)UIBezierPath對象定義一個(gè)完整的路徑包括一個(gè)或者多個(gè)subpaths。
使用UIBezierPath畫圖步驟:
- 1.創(chuàng)建一個(gè)UIBezierPath對象
- 2.調(diào)用-moveToPoint:設(shè)置初始線段的起點(diǎn)
- 3.添加線或者曲線去定義一個(gè)或者多個(gè)子路徑
- 4.改變UIBezierPath對象跟繪圖相關(guān)的屬性。如,我們可以設(shè)置畫筆的屬性、填充樣式等
詳情見
UIBezierPath_And_CAShapeLayer
===================
一、UIView 動畫
** 可實(shí)現(xiàn)動畫的屬性 **
<pre><code>坐標(biāo)尺寸類: bounds、frame、center
視圖顯示類: backgroundColor、alpha、hidden
形態(tài)變化類: transform</code></pre>
1、首尾式
** 基本寫法,代碼必須放在Begin和Commit之間: **
<pre><code>[UIView beginAnimations:nil context:nil]; // 開始動畫
// Code...
[UIView commitAnimations]; // 提交動畫</code></pre>
** 簡單例子:**
<pre><code>[UIView beginAnimations:nil context:nil]; // 開始動畫
[UIView setAnimationDuration:10.0]; // 動畫時(shí)長
/**
- 圖像向下移動
*/
CGPoint point = _imageView.center;
point.y += 150;
[_imageView setCenter:point];
[UIView commitAnimations]; // 提交動畫</code></pre>
**同時(shí)運(yùn)行多個(gè)動畫效果: **
<pre><code>[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:3.0];
[_imageView setAlpha:0.0];
[UIView commitAnimations];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:3.0];
CGPoint point = _imageView.center;
point.y += 150;
[_imageView setCenter:point];
[UIView commitAnimations];</code></pre>
以上代碼實(shí)現(xiàn)的動畫效果為(同時(shí)執(zhí)行):
1、圖像向下平移150像像
2、設(shè)置圖像透明度為0。
其它方法及屬性:
以下方法及屬性不為全部,只例舉部分:
<pre><code>// 開始動畫
- (void)beginAnimations:(NSString *)animationID context:(void *)context;
// 提交動畫
- (void)commitAnimations;
// 設(shè)置動畫曲線,默認(rèn)是勻速進(jìn)行:
- (void)setAnimationCurve:(UIViewAnimationCurve)curve;
// 設(shè)置動畫時(shí)長:
- (void)setAnimationDuration:(NSTimeInterval)duration;
// 默認(rèn)為YES。為NO時(shí)跳過動畫效果,直接跳到執(zhí)行后的狀態(tài)。
- (void)setAnimationsEnabled:(BOOL)enabled;
// 設(shè)置動畫延遲執(zhí)行(delay:秒為單位):
- (void)setAnimationDelay:(NSTimeInterval)delay;
// 動畫的重復(fù)播放次數(shù)
- (void)setAnimationRepeatCount:(float)repeatCount;
// 如果為YES,逆向(相反)動畫效果,結(jié)束后返回動畫逆向前的狀態(tài); 默認(rèn)為NO:
- (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
// 設(shè)置動畫代理:
- (void)setAnimationDelegate:(id)delegate;
// 動畫將要開始時(shí)執(zhí)行方法××(必須要先設(shè)置動畫代理):
- (void)setAnimationWillStartSelector:(SEL)selector;
// 動畫已結(jié)束時(shí)執(zhí)行方法××(必須要先設(shè)置動畫代理):
- (void)setAnimationDidStopSelector:(SEL)selector;
/**
- 設(shè)置動畫過渡效果
- @param transition 動畫的過渡效果
- @param view 過渡效果作用視圖
- @param cache 如果為YES,開始和結(jié)束視圖分別渲染一次并在動畫中創(chuàng)建幀;否則,視圖將會渲染每一幀。例如,你不需要在視圖轉(zhuǎn)變中不停的更新,你只需要等到轉(zhuǎn)換完成再去更新視圖。
*/
- (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
轉(zhuǎn)場類型
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
</code></pre>
2、block:
方法一:
<pre><code>[UIView animateWithDuration:4.0 // 動畫時(shí)長
animations:^{
// code
}];</code></pre>方法二:
<pre><code>[UIView animateWithDuration:4.0 // 動畫時(shí)長
animations:^{
// code...
}
completion:^(BOOL finished) {
// 動畫完成后執(zhí)行
// code...
}];</code></pre>
- 方法三:
<pre><code>[UIView animateWithDuration:4.0 // 動畫時(shí)長
delay:2.0 // 動畫延遲
options:UIViewAnimationOptionCurveEaseIn // 動畫過渡效果
animations:^{
// code...
}
completion:^(BOOL finished) {
// 動畫完成后執(zhí)行
// code...
}];</code></pre>
- 方法四,Spring Animationring Animation):彈簧動畫
在IOS7開始,系統(tǒng)動畫效果廣泛應(yīng)用Spring Animation:
<pre><code>[UIView animateWithDuration:4.0 // 動畫時(shí)長
delay:0.0 // 動畫延遲
usingSpringWithDamping:1.0 // 類似彈簧振動效果 0~1
initialSpringVelocity:5.0 // 初始速度
options:UIViewAnimationOptionCurveEaseInOut // 動畫過渡效果
animations:^{
// code...
CGPoint point = _imageView.center;
point.y += 150;
[_imageView setCenter:point];
} completion:^(BOOL finished) {
// 動畫完成后執(zhí)行
// code...
[_imageView setAlpha:1];
}];
</code></pre>
usingSpringWithDamping:它的范圍為 0.0f 到 1.0f ,數(shù)值越小「彈簧」的振動效果越明顯。
initialSpringVelocity:初始的速度,數(shù)值越大一開始移動越快。值得注意的是,初始速度取值較高而時(shí)間較短時(shí),也會出現(xiàn)反彈情況。
轉(zhuǎn):Spring Animation 是線性動畫或 ease-out 動畫的理想替代品。由于 iOS 本身大量使用的就是 Spring Animation,用戶已經(jīng)習(xí)慣了這種動畫效果,因此使用它能使 App 讓人感覺更加自然,用 Apple 的話說就是「instantly familiar」。此外,Spring Animation 不只能對位置使用,它適用于所有可被添加動畫效果的屬性。
-
方法六,關(guān)鍵幀動畫:
UIView動畫已經(jīng)具備高級的方法來創(chuàng)建動畫,而且可以更好地理解和構(gòu)建動畫。IOS7以后蘋果新加了一個(gè)
animateKeyframesWithDuration的方法,我們可以使用它來創(chuàng)建更多更復(fù)雜更酷炫的動畫效果,而不需要去使用到核心動畫(CoreAnimation)。
創(chuàng)建關(guān)鍵幀方法:
<pre><code>/**
- 添加關(guān)鍵幀方法
- @param duration 動畫時(shí)長
- @param delay 動畫延遲
- @param options 動畫效果選項(xiàng)
- @param animations 動畫執(zhí)行代碼
- @param completion 動畫結(jié)束執(zhí)行代碼
*/
- (void)animateKeyframesWithDuration:(NSTimeInterval)duration
delay:(NSTimeInterval)delay
options:(UIViewKeyframeAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))completion;
</code></pre>
添加關(guān)鍵幀方法:
<pre><code>/**
- 添加關(guān)鍵幀
- @param frameStartTime 動畫相對開始時(shí)間
- @param frameDuration 動畫相對持續(xù)時(shí)間
- @param animations 動畫執(zhí)行代碼
*/
- (void)addKeyframeWithRelativeStartTime:(double)frameStartTime
relativeDuration:(double)frameDuration
animations:(void (^)(void))animations;
</code></pre>以上說的相對時(shí)間,也就是說:“它們自身會根據(jù)動畫總持續(xù)時(shí)長自動匹配其運(yùn)行時(shí)長”。
<pre><code>[UIView animateKeyframesWithDuration:4.0
delay:0.0
options:UIViewKeyframeAnimationOptionCalculationModeCubic | UIViewAnimationOptionCurveLinear
animations:keyFrameBlock
completion:^(BOOL finished) {
// 動畫完成后執(zhí)行
// code...
}];
</code></pre>
動畫過渡效果(Options),新增了以下幾個(gè):
<pre><code>UIViewKeyframeAnimationOptionCalculationModeLinear = 0 << 10, // default
UIViewKeyframeAnimationOptionCalculationModeDiscrete = 1 << 10,
UIViewKeyframeAnimationOptionCalculationModePaced = 2 << 10,
UIViewKeyframeAnimationOptionCalculationModeCubic = 3 << 10,
UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10
</code></pre>
下面我們看一張圖,讓我們更容易理解:

- 方法五,轉(zhuǎn)場動畫
<pre><code>/**
- 轉(zhuǎn)場動畫
- @param fromView 當(dāng)前View
- @param toView 要顯示的View
- @param duration 動畫持續(xù)時(shí)間
- @param option 動畫類型
- @param animations 動畫執(zhí)行代碼
- @param completion 動畫結(jié)束后,會自動調(diào)用這個(gè)block
*/
- (void)transitionFromView:(UIView *)fromView
toView:(UIView *)toView
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
completion:(void (^)(BOOL finished))completion;
</code></pre>
小結(jié):
- 如果只是修改控件的屬性,使用首尾式動畫還是比較方便的,但是如果需要在動畫完成后做后續(xù)處理,就不是那么方便了。
- 在實(shí)際的開發(fā)中更常用的時(shí)block代碼塊來處理動畫操作,塊動畫相對來說比較靈活,尤為重要的是能夠?qū)赢嬒嚓P(guān)的代碼編寫在一起,便于代碼的閱讀和理解。
詳情見
UIViewAnimations Demo
補(bǔ)充
1.UIImageView的幀動畫
UIImageView可以讓一系列的圖片在特定的時(shí)間內(nèi)按順序顯示
相關(guān)屬性解析:
animationImages:要顯示的圖片(一個(gè)裝著UIImage的NSArray)
animationDuration:完整地顯示一次animationImages中的所有圖片所需的時(shí)間
animationRepeatCount:動畫的執(zhí)行次數(shù)(默認(rèn)為0,代表無限循環(huán))
相關(guān)方法解析:
- (void)startAnimating; 開始動畫
- (void)stopAnimating; 停止動畫
- (BOOL)isAnimating; 是否正在運(yùn)行動畫
</code></prep>
- 這種方法在某些場景下是可以達(dá)到逐幀的動畫效果,但是它也存在著很大的性能問題,并且這種方法一旦設(shè)置完圖片中間的過程就無法控制了。
2.UIActivityIndicatorView
是一個(gè)旋轉(zhuǎn)進(jìn)度輪,可以用來告知用戶有一個(gè)操作正在進(jìn)行中,一般用initWithActivityIndicatorStyle初始化
UIActivityIndicatorViewStyle有3個(gè)值可供選擇:
UIActivityIndicatorViewStyleWhiteLarge //大型白色指示器
UIActivityIndicatorViewStyleWhite //標(biāo)準(zhǔn)尺寸白色指示器
UIActivityIndicatorViewStyleGray //灰色指示器,用于白色背景
方法解析:
- (void)startAnimating; 開始動畫
- (void)stopAnimating; 停止動畫
- (BOOL)isAnimating; 是否正在運(yùn)行動畫
3.UIDynamic
一、簡單介紹
1.什么是UIDynamic
UIDynamic是從iOS 7開始引入的一種新技術(shù),隸屬于UIKit框架可以認(rèn)為是一種物理引擎,能模擬和仿真現(xiàn)實(shí)生活中的物理現(xiàn)象。如:重力、彈性碰撞等現(xiàn)象
2.物理引擎的價(jià)值
廣泛用于游戲開發(fā),經(jīng)典成功案例是“憤怒的小鳥”
讓開發(fā)人員可以在遠(yuǎn)離物理學(xué)公式的情況下,實(shí)現(xiàn)炫酷的物理仿真效果
提高了游戲開發(fā)效率,產(chǎn)生更多優(yōu)秀好玩的物理仿真游戲
3.知名的2D物理引擎
Box2dChipmunk
二、使用步驟
要想使用UIDynamic來實(shí)現(xiàn)物理仿真效果,大致的步驟如下
創(chuàng)建一個(gè)物理仿真器(順便設(shè)置仿真范圍)
創(chuàng)建相應(yīng)的物理仿真行為(順便添加物理仿真元素)
將物理仿真行為添加到物理仿真器中,開始仿真
三、相關(guān)說明
1.三個(gè)概念
(1)誰要進(jìn)行物理仿真?
物理仿真元素(Dynamic Item)
(2)執(zhí)行怎樣的物理仿真效果?怎樣的動畫效果?
物理仿真行為(Dynamic Behavior)
(3)讓物理仿真元素執(zhí)行具體的物理仿真行為
物理仿真器(Dynamic Animator)
2.物理仿真元素
注意:
- 不是任何對象都能做物理仿真元素
- 不是任何對象都能進(jìn)行物理仿真
物理仿真元素要素:
任何遵守了
UIDynamicItem協(xié)議的對象UIView默認(rèn)已經(jīng)遵守了UIDynamicItem協(xié)議,因此任何UI控件都能做物理仿真UICollectionViewLayoutAttributes類默認(rèn)也遵守UIDynamicItem協(xié)議
3.物理仿真行為
(1)UIDynamic提供了以下幾種物理仿真行為
UIGravityBehavior:重力行為UICollisionBehavior:碰撞行為UISnapBehavior:捕捉行為UIPushBehavior:推動行為UIAttachmentBehavior:附著行為UIDynamicItemBehavior:動力元素行為
(2)物理仿真行為須知
上述所有物理仿真行為都繼承自
UIDynamicBehavior所有的
UIDynamicBehavior都可以獨(dú)立進(jìn)行組合使用多種行為時(shí),可以實(shí)現(xiàn)一些比較復(fù)雜的效果
4. 物理仿真器
(1)物理仿真器須知
它可以讓物理仿真元素執(zhí)行物理仿真行為
它是
UIDynamicAnimator類型的對象
(2)UIDynamicAnimator的初始化
-
- (instancetype)initWithReferenceView:(UIView *)view;view參數(shù):是一個(gè)參照視圖,表示物理仿真的范圍
5.物理仿真器的說明
(1)UIDynamicAnimator的常見方法
- (void)addBehavior:(UIDynamicBehavior *)behavior;//添加1個(gè)物理仿真行為
- (void)removeBehavior:(UIDynamicBehavior *)behavior;//移除1個(gè)物理仿真行為
- (void)removeAllBehaviors;//移除之前添加過的所有物理仿真行為
(2)UIDynamicAnimator的常見屬性
@property (nonatomic, readonly) UIView* referenceView; //參照視圖
@property (nonatomic, readonly, copy) NSArray* behaviors;//添加到物理仿真器中的所有物理仿真行為
@property (nonatomic, readonly, getter = isRunning) BOOL running;//是否正在進(jìn)行物理仿真
@property (nonatomic, assign) id <UIDynamicAnimatorDelegate> delegate;//代理對象(能監(jiān)聽物理仿真器的仿真過程,比如開始和結(jié)束)
詳情見
DynamicAnimationDemo
================
二、Core Animation
什么是Animation(動畫),簡單點(diǎn)說就是在一段時(shí)間內(nèi),顯示的內(nèi)容發(fā)生了變化.對CALayer來說就是在一段時(shí)間內(nèi),其Animatable Property發(fā)生了變化.
這里涉及到兩個(gè)東西: 一是Layer(基類CALayer),一是Animation(基于CAAnimation). Animation作用于Layer.CALayer提供了接口用于給自己添加Animation.
Core Animation是一組非常強(qiáng)大的動畫處理API,使用它能做出非常絢麗的動畫效果,而且往往是事半功倍,使用它需要添加QuartzCore .framework和引入對應(yīng)的框架<QuartzCore/QuartzCore.h> .
開發(fā)步驟:
1> 初始化一個(gè)動畫對象(CAAnimation)并設(shè)置一些動畫相關(guān)屬性.
2> 添加動畫對象到層(CALayer)中,開始執(zhí)行動畫.
Core Animation的動畫執(zhí)行過程都是在后臺操作的,不會阻塞主線程.
1. CALayer
CALayer與UIView的關(guān)系
在iOS中,你能看得見摸得著的東西基本上都是UIView,比如一個(gè)按鈕、一個(gè)文本標(biāo)簽、一個(gè)文本輸入框、一個(gè)圖標(biāo)等等,這些都是UIView。
其實(shí)UIView之所以能顯示在屏幕上,完全是因?yàn)樗鼉?nèi)部的一個(gè)圖層:
-
在創(chuàng)建UIView對象時(shí),UIView內(nèi)部會自動創(chuàng)建一個(gè)圖層(即CALayer對象),通過UIView的layer屬性可以訪問這個(gè)層。
@property(nonatomic,readonly,strong) CALayer *layer;
當(dāng)UIView需要顯示到屏幕上時(shí),會調(diào)用drawRect:方法進(jìn)行繪圖,并且會將所有內(nèi)容繪制在自己的圖層上,繪圖完畢后,系統(tǒng)會將圖層拷貝到屏幕上,于是就完成了UIView的顯示。
換句話說,UIView本身不具備顯示的功能,是它內(nèi)部的層才有顯示功能。
因此,通過調(diào)節(jié)CALayer對象,可以很方便的調(diào)整UIView的一些外觀屬性。
- 對比CALayer,UIView多了一個(gè)事件處理的功能。也就是說,CALayer不能處理用戶的觸摸事件,而UIView可以。所以,如果顯示出來的東西需要跟用戶進(jìn)行交互的話,用UIView;如果不需要跟用戶進(jìn)行交互,用UIView或者CALayer都可以。當(dāng)然,CALayer的性能會高一些,因?yàn)樗倭耸录幚淼墓δ?,更加輕量級。
Layer的渲染架構(gòu)
Layer也和View一樣存在著一個(gè)層級樹狀結(jié)構(gòu),稱之為圖層樹(Layer Tree),直接創(chuàng)建的或者通過UIView獲得的(view.layer)用于顯示的圖層樹,稱之為模型樹(Model Tree),模型樹的背后還存在兩份圖層樹的拷貝,一個(gè)是呈現(xiàn)樹(Presentation Tree),一個(gè)是渲染樹(Render Tree)。

呈現(xiàn)樹可以通過普通layer(其實(shí)就是模型樹)的layer.presentationLayer獲得,而模型樹則可以通過modelLayer屬性獲得。
- 模型樹的屬性在其被修改的時(shí)候就變成了新的值,這個(gè)是可以用代碼直接操控的部分;
- 呈現(xiàn)樹的屬性值和動畫運(yùn)行過程中界面上看到的是一致的;
- 渲染樹是私有的,你無法訪問到,渲染樹是對呈現(xiàn)樹的數(shù)據(jù)進(jìn)行渲染。
為了不阻塞主線程,渲染的過程是在單獨(dú)的進(jìn)程或線程中進(jìn)行的,所以你會發(fā)現(xiàn)Animation的動畫并不會阻塞主線程.
隱式動畫
根層與非根層:
每一個(gè)UIView內(nèi)部都默認(rèn)關(guān)聯(lián)著一個(gè)CALayer,我們可用稱這個(gè)Layer為Root Layer(根層)
所有的非Root Layer,也就是手動創(chuàng)建的CALayer對象,都存在著隱式動畫
當(dāng)對非Root Layer的部分屬性進(jìn)行修改時(shí),默認(rèn)會自動產(chǎn)生一些動畫效果,而這些屬性稱為Animatable Properties(可動畫屬性)。
可以通過事務(wù)關(guān)閉隱式動畫:
CATransaction 是核心動畫里面負(fù)責(zé)協(xié)調(diào)多個(gè)動畫原子更新顯示操作。事務(wù)支持嵌套使用。
<pre><code>[CATransaction begin];
// 關(guān)閉隱式動畫
[CATransaction setDisableActions:YES];
self.myview.layer.position = CGPointMake(10, 10);
[CATransaction commit];</code></pre>
CALayer的基本屬性

<pre><code>position和anchorPoint的作用
@property CGPoint position;
用來設(shè)置CALayer在父層中的位置
以父層的左上角為原點(diǎn)(0, 0)
@property CGPoint anchorPoint;
稱為“定位點(diǎn)”、“錨點(diǎn)”,
決定著CALayer身上的哪個(gè)點(diǎn)會在position屬性所指的位置。
以自己的左上角為原點(diǎn)(0, 0),
它的x、y取值范圍都是0~1,默認(rèn)值為中心點(diǎn)(0.5, 0.5)
anchorPoint和position的關(guān)系舉例:
假如錨點(diǎn)anchorPoint為默認(rèn)值即中點(diǎn)(0.5,0.5),而該層的position設(shè)置為(0,0)即為父層的左上點(diǎn),那么該層在父層中只會看到四分之一的部分。
</code></pre>
為了進(jìn)一步說明anchorPoint的作用,假設(shè)有一個(gè)層大小100*100,現(xiàn)在中心點(diǎn)位置(50,50),由此可以得出frame(0,0,100,100)。上面說過anchorPoint默認(rèn)為(0.5,0.5),同中心點(diǎn)position重合,此時(shí)使用圖形描述如圖1;當(dāng)修改anchorPoint為(0,0),此時(shí)錨點(diǎn)處于圖層左上角,但是中心點(diǎn)poition并不會改變,因此圖層會向右下角移動,如圖2;然后修改anchorPoint為(1,1,),position還是保持位置不變,錨點(diǎn)處于圖層右下角,此時(shí)圖層如圖3。

2.CAAnimation概述
當(dāng)需要對非Root Layer進(jìn)行動畫或者需要對動畫做更多自定義的行為的時(shí)候,就必須使用到顯式動畫了,顯式動畫的基類為CAAnimation,顯式動畫不會改變該屬性的值,它只是用于動畫顯示。
- 采用了
CAMediaTiming協(xié)議:可以調(diào)整時(shí)間,包括持續(xù)時(shí)間,速度,重復(fù)次數(shù),并且能設(shè)定圖層過渡; - 采用了
CAAction協(xié)議:可以通過響應(yīng)動作的方式來顯示動畫.
來看下CAAnimation的繼承體系

CAAnimation是個(gè)抽象類,不具備動畫效果,必須用它的子類才有動畫效果。
-
CAPropertyAnimation也是個(gè)抽象類,本身不具備動畫效果,只有子類才有。
CABasicAnimation和CAKeyframeAnimation:
CABasicAnimation基本動畫,做一些簡單效果。
CAKeyframeAnimation關(guān)鍵幀動畫,做一些連續(xù)的流暢的動畫。
- CAAnimationGroup是個(gè)動畫組,可以同時(shí)進(jìn)行縮放,旋轉(zhuǎn)(同時(shí)進(jìn)行多個(gè)動畫)。
- CATransition是轉(zhuǎn)場動畫,界面之間跳轉(zhuǎn)(切換)都可以用轉(zhuǎn)場動畫。
1)CAAnimation——簡介
是所有動畫對象的父類,負(fù)責(zé)控制動畫的持續(xù)時(shí)間和速度,是個(gè)抽象類,不能直接使用,應(yīng)該使用它具體的子類。
基本屬性說明:
duration:動畫的持續(xù)時(shí)間repeatCount:重復(fù)次數(shù),無限循環(huán)可以設(shè)置HUGE_VALF或者M(jìn)AXFLOATrepeatDuration: 重復(fù)時(shí)間removedOnCompletion:默認(rèn)為YES,代表動畫執(zhí)行完畢后就從圖層上移除,圖形會恢復(fù)到動畫執(zhí)行前的狀態(tài)。如果想讓圖層保持顯示動畫執(zhí)行后的狀態(tài),那就設(shè)置為NO,不過還要設(shè)置fillMode為kCAFillModeForwards-
fillMode: 決定當(dāng)前對象在非active時(shí)間段的行為。比如動畫開始之前或者動畫結(jié)束之fillMode屬性的設(shè)置:kCAFillModeRemoved 這個(gè)是默認(rèn)值,也就是說當(dāng)動畫開始前和動畫結(jié)束后,動畫對layer都沒有影響,動畫結(jié)束后,layer會恢復(fù)到之前的狀態(tài) kCAFillModeForwards 當(dāng)動畫結(jié)束后,layer會一直保持著動畫最后的狀態(tài) kCAFillModeBackwards 在動畫開始前,只需要將動畫加入了一個(gè)layer,layer便立即進(jìn)入動畫的初始狀態(tài)并等待動畫開始。 kCAFillModeBoth 這個(gè)其實(shí)就是上面兩個(gè)的合成.動畫加入后開始之前,layer便處于動畫初始狀態(tài),動畫結(jié)束后layer保持動畫最后的狀態(tài) beginTime: 可以用來設(shè)置動畫延遲執(zhí)行時(shí)間,若想延遲2s,就設(shè)置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當(dāng)前時(shí)間-
timingFunction: 速度控制函數(shù),控制動畫運(yùn)行的節(jié)奏速度控制函數(shù)(
CAMediaTimingFunction):kCAMediaTimingFunctionLinear(線性):勻速,給你一個(gè)相對靜態(tài)的感覺 kCAMediaTimingFunctionEaseIn(漸進(jìn)):動畫緩慢進(jìn)入,然后加速離開 kCAMediaTimingFunctionEaseOut(漸出):動畫全速進(jìn)入,然后減速的到達(dá)目的地 kCAMediaTimingFunctionEaseInEaseOut(漸進(jìn)漸出):動畫緩慢的進(jìn)入,中間加速,然后減速的到達(dá)目的地。這個(gè)是默認(rèn)的動畫行為> delegate:動畫代理
CAAnimation在分類中定義了代理方法
<pre><code>
@interface NSObject (CAAnimationDelegate)
/* Called when the animation begins its active duration. */
// 動畫開始時(shí)調(diào)用
- (void)animationDidStart:(CAAnimation *)anim;
/* Called when the animation either completes its active duration or
- is removed from the object it is attached to (i.e. the layer). 'flag'
- is true if the animation reached the end of its active duration
- without being removed. */
// 動畫結(jié)束后調(diào)用
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
@end</code></pre>
2)CAPropertyAnimation
是CAAnimation的子類,也是個(gè)抽象類,要想創(chuàng)建動畫對象,應(yīng)該使用它的兩個(gè)子類:CABasicAnimation和CAKeyframeAnimation。
基本屬性說明:
keyPath: 通過指定CALayer的一個(gè)屬性名稱為keyPath(NSString類型),并且對CALayer的這個(gè)屬性的值進(jìn)行修改,達(dá)到相應(yīng)的動畫效果。比如,指定@“position”為keyPath,就修改CALayer的position屬性的值,以達(dá)到平移的動畫效果
CABasicAnimation——基本動畫
屬性說明:
fromValue: keyPath相應(yīng)屬性的初始值
toValue: keyPath相應(yīng)屬性的結(jié)束值
byValue: keyPath相應(yīng)屬性的改變值
動畫過程說明:
隨著動畫的進(jìn)行,在長度為duration的持續(xù)時(shí)間內(nèi),keyPath相應(yīng)屬性的值從fromValue漸漸地變?yōu)閠oValue。
keyPath內(nèi)容是CALayer的可動畫Animatable屬性。
如果fillMode = kCAFillModeForwards同時(shí)removedOnComletion = NO,那么在動畫執(zhí)行完畢后,圖層會保持顯示動畫執(zhí)行后的狀態(tài)。但在實(shí)質(zhì)上,圖層的屬性值還是動畫執(zhí)行前的初始值,并沒有真正被改變。
CAKeyframeAnimation——關(guān)鍵幀動畫
關(guān)鍵幀動畫,也是CAPropertyAnimation的子類,與CABasicAnimation的區(qū)別是:
CABasicAnimation只能從一個(gè)數(shù)值(fromValue)變到另一個(gè)數(shù)值(toValue),而CAKeyframeAnimation會使用一個(gè)NSArray保存這些數(shù)值
CABasicAnimation可看做是只有2個(gè)關(guān)鍵幀的CAKeyframeAnimation
屬性說明:
values: NSArray對象。里面的元素稱為“關(guān)鍵幀”(keyframe)。動畫對象會在指定的時(shí)間(duration)內(nèi),依次顯示values數(shù)組中的每一個(gè)關(guān)鍵幀
path: 可以設(shè)置一個(gè)CGPathRef、CGMutablePathRef,讓圖層按照路徑軌跡移動。path只對CALayer的anchorPoint和position起作用。如果設(shè)置了path,那么values將被忽略
keyTimes: 可以為對應(yīng)的關(guān)鍵幀指定對應(yīng)的時(shí)間點(diǎn),其取值范圍為0到1.0,keyTimes中的每一個(gè)時(shí)間值都對應(yīng)values中的每一幀。如果沒有設(shè)置keyTimes,各個(gè)關(guān)鍵幀的時(shí)間是平分的
3)CAAnimationGroup——動畫組
動畫組,是CAAnimation的子類,可以保存一組動畫對象,將CAAnimationGroup對象加入層后,組中所有動畫對象可以同時(shí)并發(fā)運(yùn)行。
默認(rèn)情況下,一組動畫對象是同時(shí)運(yùn)行的,也可以通過設(shè)置動畫對象的beginTime屬性來更改動畫的開始時(shí)間。
屬性說明:
animations: 用來保存一組動畫對象的NSArray
4)CATransition——轉(zhuǎn)場動畫
CATransition是CAAnimation的子類,用于做轉(zhuǎn)場動畫,能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭赢嬓Ч?。iOS比Mac OS X的轉(zhuǎn)場動畫效果少一點(diǎn)。
UINavigationController就是通過CATransition實(shí)現(xiàn)了將控制器的視圖推入屏幕的動畫效果。
屬性說明:
type: 動畫過渡類型

subtype: 動畫過度方向

startProgress: 動畫起點(diǎn)(在整體動畫的百分比)
endProgress: 動畫終點(diǎn)(在整體動畫的百分比)
步驟
1.創(chuàng)建轉(zhuǎn)場動畫
2.設(shè)置轉(zhuǎn)場類型、子類型(可選)及其他屬性
3.設(shè)置轉(zhuǎn)場后的新視圖并添加動畫到圖層
舉例
<pre><code>CATransition *anim = [CATransition animation];
anim.type = @"cube";
anim.subtype = kCATransitionFromBottom;
[view.layer addAnimation:anim forKey:nil];
</code></pre>
詳情見KKCoreAnimation&&SKBounceAnimation
3.補(bǔ)充
1)CASpringAnimation
iOS9才引入的動畫類,它繼承于CABaseAnimation,用于制作彈簧動畫
參數(shù)說明
mass://質(zhì)量,影響圖層運(yùn)動時(shí)的彈簧慣性,質(zhì)量越大,彈簧拉伸和壓縮的幅度越大,動畫的速度變慢,并且波動幅度變大
stiffness://剛度系數(shù)(勁度系數(shù)/彈性系數(shù)),剛度系數(shù)越大,形變產(chǎn)生的力就越大,運(yùn)動越快
damping://阻尼系數(shù),阻止彈簧伸縮的系數(shù),阻尼系數(shù)越大,停止越快
initialVelocity://初始速率,動畫視圖的初始速度大小
速率為正數(shù)時(shí),速度方向與運(yùn)動方向一致,速率為負(fù)數(shù)時(shí),速度方向與運(yùn)動方向相反
settlingDuration://結(jié)算時(shí)間 返回彈簧動畫到停止時(shí)的估算時(shí)間,根據(jù)當(dāng)前的動畫參數(shù)估算
通常彈簧動畫的時(shí)間使用結(jié)算時(shí)間比較準(zhǔn)確
2)CAShapeLayer:
CAShapeLayer顧名思義,繼承于CALayer。 每個(gè)CAShapeLayer對象都代表著將要被渲染到屏幕上的一個(gè)任意的形狀(shape)。具體的形狀由其path(類型為CGPathRef)屬性指定。 普通的CALayer是矩形,所以需要frame屬性。CAShapeLayer初始化時(shí)也需要指定frame值,但 它本身沒有形狀,它的形狀來源于其屬性path 。CAShapeLayer有不同于CALayer的屬性,它從CALayer繼承而來的屬性在繪制時(shí)是不起作用的。
3)CADisplayLink
CADisplayLink是一個(gè)計(jì)時(shí)器,但是同NSTimer不同的是,CADisplayLink的刷新周期同屏幕完全一致。例如在iOS中屏幕刷新周期是60次/秒,CADisplayLink刷新周期同屏幕刷新一致也是60次/秒,這樣一來使用它完成的逐幀動畫(又稱為“時(shí)鐘動畫”)完全感覺不到動畫的停滯情況。
iOS程序在運(yùn)行后就進(jìn)入一個(gè)消息循環(huán)中(這個(gè)消息循環(huán)稱為“主運(yùn)行循環(huán)”),整個(gè)程序相當(dāng)于進(jìn)入一個(gè)死循環(huán)中,始終等待用戶輸入。將CADisplayLink加入到主運(yùn)行循環(huán)隊(duì)列后,它的時(shí)鐘周期就和主運(yùn)行循環(huán)保持一致,而主運(yùn)行循環(huán)周期就是屏幕刷新周期。在CADisplayLink加入到主運(yùn)行循環(huán)隊(duì)列后就會循環(huán)調(diào)用目標(biāo)方法,在這個(gè)方法中更新視圖內(nèi)容就可以完成逐幀動畫。
使用方法:
<pre><code>定義CADisplayLink并制定觸發(fā)調(diào)用方法
將顯示鏈接添加到主運(yùn)行循環(huán)隊(duì)列
// 定義
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotationChange)];
// 添加到主循環(huán)隊(duì)列
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
開始和暫停
// 暫停
link.paused = YES;
// 開始
link.paused = NO;
</code></pre>
三、FaceBook POP動畫
1.工作機(jī)制
POP是一個(gè)在iOS與OS X上通用的極具擴(kuò)展性的動畫引擎 它在基本的靜態(tài)動畫的基礎(chǔ)上增加的彈簧動畫與衰減動畫。
使之能創(chuàng)造出更真實(shí)更具物理性的交互動畫 POP的API可以快速的與現(xiàn)有的ObjC代碼集成并可以作用于任意對象的任意屬性。
POP 本質(zhì)上是基于定時(shí)器的動畫庫,使用每秒 60 頻率的定時(shí)器,即時(shí)鐘頻率為 1/60 秒(為了匹配 iOS 顯示屏幀率),使得動畫刷新繪制頻率與屏幕刷新頻率一致。很多這類動畫庫都使用 CADisplayLink 做為一個(gè)回調(diào)源。
在計(jì)算機(jī)的世界里面,其實(shí)并不存在絕對連續(xù)的動畫,你所看到的屏幕上的動畫本質(zhì)上都是離散的,只是在一秒的時(shí)間里面離散的幀多到一定的數(shù)量人眼就覺得是連續(xù)的了,在iOS中,最大的幀率是60幀每秒。 iOS提供了Core Animation框架,只需要開發(fā)者提供關(guān)鍵幀信息,比如提供某個(gè)animatable屬性終點(diǎn)的關(guān)鍵幀信息,然后中間的值則通過一定的算法進(jìn)行插值計(jì)算,從而實(shí)現(xiàn)補(bǔ)間動畫。 Core Aniamtion中進(jìn)行插值計(jì)算所依賴的時(shí)間曲線由CAMediaTimingFunction提供。 Pop Animation在使用上和Core Animation很相似,都涉及Animation對象以及Animation的載體的概念,不同的是Core Animation的載體只能是CALayer,而Pop Animation可以是任意基于NSObject的對象。當(dāng)然大多數(shù)情況Animation都是界面上顯示的可視的效果,所以動畫執(zhí)行的載體一般都直接或者間接是UIView或者CALayer。
-
Pop Animation相比于Core Animation的優(yōu)點(diǎn)
1. Pop Animation應(yīng)用于CALayer時(shí),在動畫運(yùn)行的任何時(shí)刻,layer和其presentationLayer的相關(guān)屬性值始終保持一致,而Core Animation做不到。 2.Pop Animation可以應(yīng)用任何NSObject的對象,而Core Aniamtion必須是CALayer。
2.源碼結(jié)構(gòu):

代碼包括四個(gè)目錄:
Animations: 定義pop支持的動畫類型,并抽像各種動畫的低層數(shù)據(jù)結(jié)構(gòu)
Engine:組織動化運(yùn)行的數(shù)據(jù)結(jié)構(gòu),核心是動化管理者,還包括了動畫引擎所需要的可動畫屬性定義、動畫追蹤等內(nèi)容
Utility: 封裝Engine中用到的各種功能,包括數(shù)值運(yùn)算,數(shù)據(jù)轉(zhuǎn)換,運(yùn)算等
WebCore: 這部分是蘋果公司的代碼,矩陣運(yùn)算和貝賽爾曲線的,用于底層運(yùn)算。
1)Animations
POPAnimation :定義了動畫基類POPAnimation
私有變量:結(jié)構(gòu)體`_POPAnimationState` 紀(jì)錄動畫狀態(tài),是實(shí)現(xiàn)動畫最關(guān)鍵的屬性
公有變量:name beginTime delegate tracer(動畫追蹤,紀(jì)錄各種動畫事件) ^completionBlock removedOnCompletion paused
繼承關(guān)系:
NSObject
POPAnimation
POPPropertyAnimation
POPBasicAnimation
POPDecayAnimation
POPSpringAnimation
POPCustomAnimation
_POPAnimationState
_POPPropertyAnimationState
_POPBasicAnimationState
_POPDecayAnimationState
_POPSpringAnimationState
NSObject (POP)讓所有對象增加pop動畫支持(增刪改查)通過POPAnimator進(jìn)行管理
2)Engine
POPAnimateableProperty 可動畫的屬性,用于定義動畫類型和動畫時(shí)修改值
POPStaticAnimatablePropertyState 結(jié)構(gòu)體紀(jì)錄了屬性名,readBlock,writeBlock,和域值
POPStaticAnimatablePropertyState _staticStates[] 紀(jì)錄了所有可動畫的屬性對應(yīng)的名稱,其中的writeblock功能是把二進(jìn)制數(shù)據(jù)寫到對應(yīng)的屬性里
類族:
POPAnimatableProperty
POPConcreteAnimatableProperty
POPMutableAnimatableProperty
POPPlaceholderAnimatableProperty
POPStaticAnimatableProperty
POPAnimationEvent POPAnimationTracer的基本元素
POPAnimationExtras 擴(kuò)展CAAnimation 和POPSpringAnimation 的方法(分類)
POPAnimationRuntime 這里有幾個(gè)函數(shù)比較特殊
POPBox 包裝一個(gè)函數(shù)vector,把vector轉(zhuǎn)化為point,size,rect,color等
POPUnbox 解包一個(gè)向量,把point,size,rect,color對象轉(zhuǎn)換為vector
POPAnimationTracer 動畫跟蹤 通過POPAnimationEvent來描述
POPAnimator 動畫管理者,紀(jì)錄所有的動畫事件(POPAnimatorItem,紀(jì)錄了動畫作用到的對象、動畫key、動畫對象等信息),初始化是把CADisplayLink注冊到runloop里定時(shí)觸發(fā)render過程,進(jìn)行一幀動畫渲染。她提供了add、remove等操作Animation集合的方法,并提供了Observer和delegate等事件函數(shù)
POPAnimator通過兩層(key,view)存儲動畫,(動畫目標(biāo)對象,(動畫key,動畫對象))
具體每幀的渲染過程有兩步:1.renderTime,更新state的狀態(tài)。 2.updateAnimatable,把state的變化更新到obj的具體屬性上
3)Utility 各種工具類
POPAction: ActionDisabler和ActionEnabler 利用RAII暫停核心動畫以ActionEnabler為例,創(chuàng)建ActionEnabler時(shí)停止動畫,銷毀時(shí)重新運(yùn)行動畫
POPCGUtils:顏色轉(zhuǎn)換函數(shù),數(shù)組和點(diǎn),point,size,rect,color等轉(zhuǎn)換函數(shù)
POPGeometry:擴(kuò)展NSValue到POP自定義類型的轉(zhuǎn)換
POPLayerExtras:圖層矩陣變換封裝,底層由TransformationMatrix實(shí)現(xiàn)
POPMath:數(shù)學(xué)計(jì)算接口,封裝了UnitBezier,POPVector和其他數(shù)字計(jì)算
SpringSolver:spring插值計(jì)算
POPVector:向量運(yùn)算
4)WebCore
FloatConversion:浮點(diǎn)數(shù)轉(zhuǎn)換方法,提供double->float和double->CGFloat,
用途:服務(wù)于矩陣運(yùn)算
TransformationMatrix:矩陣運(yùn)算,包括初始化,scale,rotate,translate,flipX,flipY,skew,applyPerspective???,multVecMatrix向量和矩陣相乘等矩陣操作,
CATransform3D 矩陣變換之立方體旋轉(zhuǎn)實(shí)現(xiàn)細(xì)節(jié)
關(guān)鍵方法說明:
計(jì)算行列式的值:不列舉了,很枯燥,行列式計(jì)算的基本概念,從二階計(jì)算到三階再計(jì)算到四階。主要作用是引擎層對layer進(jìn)行坐標(biāo)變換
UnitBezier: 結(jié)構(gòu)體,初始化參數(shù)為兩個(gè)控制點(diǎn)p1(p1x,p1y),p2(p2x,p2y),用于表示起始點(diǎn)為s(0,0),終止點(diǎn)為e(1,1),p1為第一控制點(diǎn),p2為第二控制點(diǎn)的二次Bezier。
用途:重新實(shí)現(xiàn)系統(tǒng)的自帶動畫
方法說明:
UnitBezier(double p1x, double p1y, double p2x, double p2y)//用兩個(gè)控制點(diǎn)的坐標(biāo)初始化曲線,
double sampleCurveX(double t)//通過參數(shù)t計(jì)算對應(yīng)的x值
double sampleCurveY(double t)//通過參數(shù)t計(jì)算對應(yīng)的y值
double sampleCurveDerivativeX(double t)
//epsilon表示一個(gè)小間距,相當(dāng)于數(shù)學(xué)計(jì)算里的dX,一般為全距離的1/1000,
//求解x對應(yīng)的t值,用到了函數(shù)sampleCurveDerivativeX
double solveCurveX(double x, double epsilon)
double solve(double x, double epsilon)//求解x對應(yīng)的y值,分為兩步算,1.由x計(jì)算t;2.由t計(jì)算y
3.動畫執(zhí)行流程:
1)POPAnimator是單例對象,初始化對象實(shí)例時(shí)注冊把CADisplayLink到runloop,定時(shí)調(diào)用render,通過renderTime函數(shù)遍歷所有正在執(zhí)行的動畫,使動畫進(jìn)行到下一幀,并刷新畫面,直到所有動畫推進(jìn)完成。
2)動畫狀態(tài)的推進(jìn)最終都是通過_POPAnimationState類和其子類的advance方法推進(jìn)的,advance更新時(shí)間戳,updateAnimatable方法把state的狀態(tài)變更到動畫要作用的obj對象。
3)Spring、Decay、Basic 都有各自實(shí)現(xiàn)的advance函數(shù)計(jì)算,而Custom方式不同,他是通過一個(gè)POPCustomAnimationBlock類型的回調(diào)來就算這一幀的值的。
4.動畫使用
1)POPBasicAnimation
基本動畫,接口方面和CABasicAniamtion很相似,使用可以提供初始值fromValue,這個(gè) 終點(diǎn)值toValue,動畫時(shí)長duration以及決定動畫節(jié)奏的timingFunction。timingFunction直接使用的CAMediaTimingFunction,是使用一個(gè)橫向縱向都為一個(gè)單位的擁有兩個(gè)控制點(diǎn)的貝賽爾曲線來描述的,橫坐標(biāo)為時(shí)間,縱坐標(biāo)為動畫進(jìn)度。

NSInteger height = CGRectGetHeight(self.view.bounds);
NSInteger width = CGRectGetWidth(self.view.bounds);
CGFloat centerX = arc4random() % width;
CGFloat centerY = arc4random() % height;
POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerY)];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.duration = 0.4;
[self.testView pop_addAnimation:anim forKey:@"centerAnimation"];
2)PopSpringAnimation
彈簧動畫是Bezier曲線無法表述的,所以無法使用PopBasicAniamtion來實(shí)現(xiàn)。PopSpringAnimation便是專門用來實(shí)現(xiàn)彈簧動畫的。

POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
NSInteger height = CGRectGetHeight(self.view.bounds);
NSInteger width = CGRectGetWidth(self.view.bounds);
CGFloat centerX = arc4random() % width;
CGFloat centerY = arc4random() % height;
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerY)];
anim.springBounciness = 16;
anim.springSpeed = 6;
[self.testView pop_addAnimation:anim forKey:@"center"];
屬性介紹
springBounciness彈簧彈力 取值范圍為[0, 20],默認(rèn)值為4springSpeed彈簧速度,速度越快,動畫時(shí)間越短 [0, 20],默認(rèn)為12,和springBounciness一起決定著彈簧動畫的效果dynamicsTension彈簧的張力dynamicsFriction彈簧摩擦dynamicsMass質(zhì)量 。張力,摩擦,質(zhì)量這三者可以從更細(xì)的粒度上替代springBounciness和springSpeed控制彈簧動畫的效果
3)PopDecayAnimation
基于Bezier曲線的timingFuntion同樣無法表述Decay Aniamtion,所以Pop就單獨(dú)實(shí)現(xiàn)了一個(gè) PopDecayAnimation,用于衰減動畫。衰減動畫一個(gè)很常見的地方就是 UIScrollView 滑動松開后的減速,這里就基于UIView實(shí)現(xiàn)一個(gè)自己的ScrollView,然后使用PopDecayAnimation實(shí)現(xiàn) 此代碼可以詳細(xì)參見 KKScrollView 的實(shí)現(xiàn),當(dāng)滑動手勢結(jié)束時(shí),根據(jù)結(jié)束的加速度,給衰減動畫一個(gè)初始的velocity,用來決定衰減的時(shí)長。

4)POPCustomAnimation
通過自定義block刷新動畫幀,更靈活的方式
POPCustomAnimation 并不是基于POPPropertyAnimation的,它直接繼承自PopAnimation用于創(chuàng)建自定義動畫用的,通過POPCustomAnimationBlock類型的block進(jìn)行初始化,
typedef BOOL (^POPCustomAnimationBlock)(id target, POPCustomAnimation *animation);
此block會在界面的每一幀更新的時(shí)候被調(diào)用,創(chuàng)建者需要在block中根據(jù)當(dāng)前currentTime和elapsedTime來決定如何更新target的相關(guān)屬性,以實(shí)現(xiàn)特定的動畫。當(dāng)你需要結(jié)束動畫的時(shí)候就在block中返回NO,否則返回YES。
詳情見
facebook-pop-sample&&POP-Handapp