iOS動畫知識


目錄

  • ** 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>
下面我們看一張圖,讓我們更容易理解:

alt animation
alt animation
  • 方法五,轉(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物理引擎
  • Box2d

  • Chipmunk

二、使用步驟

要想使用UIDynamic來實(shí)現(xiàn)物理仿真效果,大致的步驟如下

  1. 創(chuàng)建一個(gè)物理仿真器(順便設(shè)置仿真范圍)

  2. 創(chuàng)建相應(yīng)的物理仿真行為(順便添加物理仿真元素)

  3. 將物理仿真行為添加到物理仿真器中,開始仿真

三、相關(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)AXFLOAT

  • repeatDuration: 重復(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è)子類:CABasicAnimationCAKeyframeAnimation

基本屬性說明:
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: 動畫過度方向

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)值為4

  • springSpeed 彈簧速度,速度越快,動畫時(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,698評論 6 30
  • 學(xué)習(xí)及實(shí)踐筆記 記錄iOS動畫的學(xué)習(xí)及實(shí)踐 目錄 顯示層(UIView)動畫初級動畫關(guān)鍵幀動畫逐幀動畫Gif動畫的...
    Tr2e閱讀 2,748評論 8 45
  • 在iOS中隨處都可以看到絢麗的動畫效果,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,273評論 5 13
  • 先看看CAAnimation動畫的繼承結(jié)構(gòu) CAAnimation{ CAPropertyAnimation { ...
    時(shí)間不會倒著走閱讀 1,800評論 0 1
  • 一、CoreAnimation(核心動畫) 1.什么是核心動畫 Core Animation可以用在 Mac OS...
    就叫yang閱讀 9,295評論 1 34

友情鏈接更多精彩內(nèi)容