iOS動(dòng)畫(huà)知識(shí)


目錄

  • ** UIView 動(dòng)畫(huà) **
  • ** Core Animation **
  • ** FaceBook POP動(dòng)畫(huà) **

在iOS中,圖形可分為以下幾個(gè)層次:


<p>OpenGL ES使用硬件加速接口來(lái)處理先進(jìn)的2d 和3d 呈現(xiàn)。OpenGLES通常由游戲開(kāi)發(fā)者或想實(shí)現(xiàn)沉浸式圖像體驗(yàn)的開(kāi)發(fā)者使用。OpenGLES框架提供對(duì)呈現(xiàn)過(guò)程的全部控制,以及提供創(chuàng)建平滑動(dòng)畫(huà)所需要的幀速。</p>

  • 創(chuàng)建2D和3D圖形
  • 創(chuàng)建更復(fù)雜的圖形,比如數(shù)據(jù)虛擬化、模擬飛行,或者視頻游戲
  • 訪問(wèn)底層圖形設(shè)備

<p>Core Graphics也稱作Quartz,是對(duì)定制的2D向量和圖像呈現(xiàn)提供支持的本地繪制引擎。該框架提供的引擎雖然沒(méi)有OpenGLES引擎速度快,但該框架能夠很好地適合于呈現(xiàn)定制的2d圖形和動(dòng)態(tài)圖像。</p>

  • 創(chuàng)建基于路徑的繪圖
  • 抗鋸齒渲染
  • 添加梯度、圖片和顏色
  • Use coordinate-space transformations.
  • 創(chuàng)建、顯示和分析PDF文檔

<p>Core Animation也是Quartz核心框架的一部分,是優(yōu)化應(yīng)用動(dòng)畫(huà)體驗(yàn)的基礎(chǔ)技術(shù)。使用Core Animation可以創(chuàng)建嵌套的對(duì)象,并且可以對(duì)它們操作、旋轉(zhuǎn)、縮放和轉(zhuǎn)換。使用Core animation,你可以創(chuàng)建動(dòng)態(tài)的用戶界面而不用使用更底層的圖形API,如OpenGL ES。</p>

  • 創(chuàng)建定制動(dòng)畫(huà)
  • 添加定時(shí)函數(shù)和圖形
  • 支持幀動(dòng)畫(huà)
  • Specify graphical layout constraints.
  • Group multiple-layer changes into anatomic update.

<p>UIKit視圖基于 Core Animation提供視圖級(jí)別的動(dòng)畫(huà)支持。</p>

實(shí)現(xiàn)動(dòng)畫(huà)三要素

  • 元素(who)
  • 行為(how)
  • 執(zhí)行(do)

兩個(gè)概念

1.仿射變換(Affine Transformation或 Affine Map)

是一種二維坐標(biāo)到二維坐標(biāo)之間的線性變換,它保持了二維圖形的“平直性”(即:直線經(jīng)過(guò)變換之后依然是直線)和“平行性”(即:二維圖形之間的相對(duì)位置關(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),所以有用的信息就是前面兩列

對(duì)一個(gè)view進(jìn)行仿射變化就相當(dāng)于對(duì)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>仿射變換可以通過(guò)一系列的原子變換的復(fù)合來(lái)實(shí)現(xiàn),包括:平移(Translation)、縮放(Scale)、翻轉(zhuǎn)(Flip)、旋轉(zhuǎn)(Rotation)和錯(cuò)切(Shear)。
</p>

  • 常用函數(shù)
    <pre><code>/// 用來(lái)連接兩個(gè)變換效果并返回。返回的t = t1 * t2
    CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2)

/// 矩陣初始值。[ 1 0 0 1 0 0 ]
CGAffineTransformIdentity

/// 自定義矩陣變換,需要掌握矩陣變換的知識(shí)才知道怎么用。參照(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)。
通過(guò)調(diào)整控制點(diǎn),貝塞爾曲線的形狀會(huì)發(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)用在動(dòng)畫(huà)中,描述物件的運(yùn)動(dòng)路徑等等。

UIBezierPath

使用UIBezierPath類可以創(chuàng)建基于矢量的路徑,這個(gè)類在UIKit中。此類是Core Graphics框架關(guān)于CGPathRef的一個(gè)封裝。

path如果是基于矢量形狀的,都用直線和曲線段去創(chuàng)建。 我們使用直線段去創(chuàng)建矩形和多邊形,使用曲線段去創(chuàng)建弧(arc),圓或者其他復(fù)雜的曲線形狀。 每一段都包括一個(gè)或者多個(gè)點(diǎn),繪圖命令定義如何去詮釋這些點(diǎn)。每一個(gè)直線段或者曲線段的結(jié)束的地方是下一個(gè)的開(kāi)始的地方。每一個(gè)連接的直線或者曲線段的集合成為subpath。一個(gè)UIBezierPath對(duì)象定義一個(gè)完整的路徑包括一個(gè)或者多個(gè)subpaths。

使用UIBezierPath畫(huà)圖步驟:

  • 1.創(chuàng)建一個(gè)UIBezierPath對(duì)象
  • 2.調(diào)用-moveToPoint:設(shè)置初始線段的起點(diǎn)
  • 3.添加線或者曲線去定義一個(gè)或者多個(gè)子路徑
  • 4.改變UIBezierPath對(duì)象跟繪圖相關(guān)的屬性。如,我們可以設(shè)置畫(huà)筆的屬性、填充樣式等

詳情見(jiàn)UIBezierPath_And_CAShapeLayer

===================

一、UIView 動(dòng)畫(huà)

** 可實(shí)現(xiàn)動(dòng)畫(huà)的屬性 **
<pre><code>坐標(biāo)尺寸類: bounds、frame、center
視圖顯示類: backgroundColor、alpha、hidden
形態(tài)變化類: transform</code></pre>

1、首尾式

** 基本寫(xiě)法,代碼必須放在Begin和Commit之間: **
<pre><code>[UIView beginAnimations:nil context:nil]; // 開(kāi)始動(dòng)畫(huà)
// Code...
[UIView commitAnimations]; // 提交動(dòng)畫(huà)</code></pre>

** 簡(jiǎn)單例子:**
<pre><code>[UIView beginAnimations:nil context:nil]; // 開(kāi)始動(dòng)畫(huà)
[UIView setAnimationDuration:10.0]; // 動(dòng)畫(huà)時(shí)長(zhǎng)

/**

  • 圖像向下移動(dòng)
    */
    CGPoint point = _imageView.center;
    point.y += 150;
    [_imageView setCenter:point];

[UIView commitAnimations]; // 提交動(dòng)畫(huà)</code></pre>

**同時(shí)運(yùn)行多個(gè)動(dòng)畫(huà)效果: **

<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)的動(dòng)畫(huà)效果為(同時(shí)執(zhí)行):

1、圖像向下平移150像像
2、設(shè)置圖像透明度為0。

其它方法及屬性:

以下方法及屬性不為全部,只例舉部分:

<pre><code>// 開(kāi)始動(dòng)畫(huà)

  • (void)beginAnimations:(NSString *)animationID context:(void *)context;

// 提交動(dòng)畫(huà)

  • (void)commitAnimations;

// 設(shè)置動(dòng)畫(huà)曲線,默認(rèn)是勻速進(jìn)行:

  • (void)setAnimationCurve:(UIViewAnimationCurve)curve;

// 設(shè)置動(dòng)畫(huà)時(shí)長(zhǎng):

  • (void)setAnimationDuration:(NSTimeInterval)duration;

// 默認(rèn)為YES。為NO時(shí)跳過(guò)動(dòng)畫(huà)效果,直接跳到執(zhí)行后的狀態(tài)。

  • (void)setAnimationsEnabled:(BOOL)enabled;

// 設(shè)置動(dòng)畫(huà)延遲執(zhí)行(delay:秒為單位):

  • (void)setAnimationDelay:(NSTimeInterval)delay;

// 動(dòng)畫(huà)的重復(fù)播放次數(shù)

  • (void)setAnimationRepeatCount:(float)repeatCount;

// 如果為YES,逆向(相反)動(dòng)畫(huà)效果,結(jié)束后返回動(dòng)畫(huà)逆向前的狀態(tài); 默認(rèn)為NO:

  • (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;

// 設(shè)置動(dòng)畫(huà)代理:

  • (void)setAnimationDelegate:(id)delegate;

// 動(dòng)畫(huà)將要開(kāi)始時(shí)執(zhí)行方法××(必須要先設(shè)置動(dòng)畫(huà)代理):

  • (void)setAnimationWillStartSelector:(SEL)selector;

// 動(dòng)畫(huà)已結(jié)束時(shí)執(zhí)行方法××(必須要先設(shè)置動(dòng)畫(huà)代理):

  • (void)setAnimationDidStopSelector:(SEL)selector;

/**

  • 設(shè)置動(dòng)畫(huà)過(guò)渡效果
  • @param transition 動(dòng)畫(huà)的過(guò)渡效果
  • @param view 過(guò)渡效果作用視圖
  • @param cache 如果為YES,開(kāi)始和結(jié)束視圖分別渲染一次并在動(dòng)畫(huà)中創(chuàng)建幀;否則,視圖將會(huì)渲染每一幀。例如,你不需要在視圖轉(zhuǎn)變中不停的更新,你只需要等到轉(zhuǎn)換完成再去更新視圖。
    */
  • (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;

轉(zhuǎn)場(chǎng)類型
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
</code></pre>

2、block:

  • 方法一:
    <pre><code>[UIView animateWithDuration:4.0 // 動(dòng)畫(huà)時(shí)長(zhǎng)
    animations:^{
    // code
    }];</code></pre>

  • 方法二:
    <pre><code>[UIView animateWithDuration:4.0 // 動(dòng)畫(huà)時(shí)長(zhǎng)
    animations:^{
    // code...
    }
    completion:^(BOOL finished) {
    // 動(dòng)畫(huà)完成后執(zhí)行
    // code...
    }];</code></pre>

  • 方法三:

<pre><code>[UIView animateWithDuration:4.0 // 動(dòng)畫(huà)時(shí)長(zhǎng)
delay:2.0 // 動(dòng)畫(huà)延遲
options:UIViewAnimationOptionCurveEaseIn // 動(dòng)畫(huà)過(guò)渡效果
animations:^{
// code...
}
completion:^(BOOL finished) {
// 動(dòng)畫(huà)完成后執(zhí)行
// code...
}];</code></pre>

  • 方法四,Spring Animationring Animation):彈簧動(dòng)畫(huà)

在IOS7開(kāi)始,系統(tǒng)動(dòng)畫(huà)效果廣泛應(yīng)用Spring Animation:

<pre><code>[UIView animateWithDuration:4.0 // 動(dòng)畫(huà)時(shí)長(zhǎng)
delay:0.0 // 動(dòng)畫(huà)延遲
usingSpringWithDamping:1.0 // 類似彈簧振動(dòng)效果 0~1
initialSpringVelocity:5.0 // 初始速度
options:UIViewAnimationOptionCurveEaseInOut // 動(dòng)畫(huà)過(guò)渡效果
animations:^{
// code...
CGPoint point = _imageView.center;
point.y += 150;
[_imageView setCenter:point];
} completion:^(BOOL finished) {
// 動(dòng)畫(huà)完成后執(zhí)行
// code...
[_imageView setAlpha:1];
}];
</code></pre>
usingSpringWithDamping:它的范圍為 0.0f 到 1.0f ,數(shù)值越小「彈簧」的振動(dòng)效果越明顯。
initialSpringVelocity:初始的速度,數(shù)值越大一開(kāi)始移動(dòng)越快。值得注意的是,初始速度取值較高而時(shí)間較短時(shí),也會(huì)出現(xiàn)反彈情況。

轉(zhuǎn):Spring Animation 是線性動(dòng)畫(huà)或 ease-out 動(dòng)畫(huà)的理想替代品。由于 iOS 本身大量使用的就是 Spring Animation,用戶已經(jīng)習(xí)慣了這種動(dòng)畫(huà)效果,因此使用它能使 App 讓人感覺(jué)更加自然,用 Apple 的話說(shuō)就是「instantly familiar」。此外,Spring Animation 不只能對(duì)位置使用,它適用于所有可被添加動(dòng)畫(huà)效果的屬性。
  • 方法六,關(guān)鍵幀動(dòng)畫(huà):

    UIView動(dòng)畫(huà)已經(jīng)具備高級(jí)的方法來(lái)創(chuàng)建動(dòng)畫(huà),而且可以更好地理解和構(gòu)建動(dòng)畫(huà)。IOS7以后蘋(píng)果新加了一個(gè)animateKeyframesWithDuration的方法,我們可以使用它來(lái)創(chuàng)建更多更復(fù)雜更酷炫的動(dòng)畫(huà)效果,而不需要去使用到核心動(dòng)畫(huà)(CoreAnimation)。

創(chuàng)建關(guān)鍵幀方法:

<pre><code>/**

  • 添加關(guān)鍵幀方法
  • @param duration 動(dòng)畫(huà)時(shí)長(zhǎng)
  • @param delay 動(dòng)畫(huà)延遲
  • @param options 動(dòng)畫(huà)效果選項(xiàng)
  • @param animations 動(dòng)畫(huà)執(zhí)行代碼
  • @param completion 動(dòng)畫(huà)結(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 動(dòng)畫(huà)相對(duì)開(kāi)始時(shí)間
  • @param frameDuration 動(dòng)畫(huà)相對(duì)持續(xù)時(shí)間
  • @param animations 動(dòng)畫(huà)執(zhí)行代碼
    */
  • (void)addKeyframeWithRelativeStartTime:(double)frameStartTime
    relativeDuration:(double)frameDuration
    animations:(void (^)(void))animations;
    </code></pre>以上說(shuō)的相對(duì)時(shí)間,也就是說(shuō):“它們自身會(huì)根據(jù)動(dòng)畫(huà)總持續(xù)時(shí)長(zhǎng)自動(dòng)匹配其運(yùn)行時(shí)長(zhǎng)”。

<pre><code>[UIView animateKeyframesWithDuration:4.0
delay:0.0
options:UIViewKeyframeAnimationOptionCalculationModeCubic | UIViewAnimationOptionCurveLinear
animations:keyFrameBlock
completion:^(BOOL finished) {
// 動(dòng)畫(huà)完成后執(zhí)行
// code...
}];
</code></pre>
動(dòng)畫(huà)過(guò)渡效果(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)場(chǎng)動(dòng)畫(huà)

<pre><code>/**

  • 轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
  • @param fromView 當(dāng)前View
  • @param toView 要顯示的View
  • @param duration 動(dòng)畫(huà)持續(xù)時(shí)間
  • @param option 動(dòng)畫(huà)類型
  • @param animations 動(dòng)畫(huà)執(zhí)行代碼
  • @param completion 動(dòng)畫(huà)結(jié)束后,會(huì)自動(dòng)調(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é):

  • 如果只是修改控件的屬性,使用首尾式動(dòng)畫(huà)還是比較方便的,但是如果需要在動(dòng)畫(huà)完成后做后續(xù)處理,就不是那么方便了。
  • 在實(shí)際的開(kāi)發(fā)中更常用的時(shí)block代碼塊來(lái)處理動(dòng)畫(huà)操作,塊動(dòng)畫(huà)相對(duì)來(lái)說(shuō)比較靈活,尤為重要的是能夠?qū)?dòng)畫(huà)相關(guān)的代碼編寫(xiě)在一起,便于代碼的閱讀和理解。

詳情見(jiàn)UIViewAnimations Demo

補(bǔ)充

1.UIImageView的幀動(dòng)畫(huà)

UIImageView可以讓一系列的圖片在特定的時(shí)間內(nèi)按順序顯示

相關(guān)屬性解析:

animationImages:要顯示的圖片(一個(gè)裝著UIImage的NSArray)

animationDuration:完整地顯示一次animationImages中的所有圖片所需的時(shí)間

animationRepeatCount:動(dòng)畫(huà)的執(zhí)行次數(shù)(默認(rèn)為0,代表無(wú)限循環(huán))

相關(guān)方法解析:

- (void)startAnimating; 開(kāi)始動(dòng)畫(huà)

- (void)stopAnimating;  停止動(dòng)畫(huà)

- (BOOL)isAnimating;  是否正在運(yùn)行動(dòng)畫(huà)

</code></prep>

  • 這種方法在某些場(chǎng)景下是可以達(dá)到逐幀的動(dòng)畫(huà)效果,但是它也存在著很大的性能問(wèn)題,并且這種方法一旦設(shè)置完圖片中間的過(guò)程就無(wú)法控制了。

2.UIActivityIndicatorView

是一個(gè)旋轉(zhuǎn)進(jìn)度輪,可以用來(lái)告知用戶有一個(gè)操作正在進(jìn)行中,一般用initWithActivityIndicatorStyle初始化

UIActivityIndicatorViewStyle有3個(gè)值可供選擇:

UIActivityIndicatorViewStyleWhiteLarge   //大型白色指示器    

UIActivityIndicatorViewStyleWhite        //標(biāo)準(zhǔn)尺寸白色指示器    

UIActivityIndicatorViewStyleGray         //灰色指示器,用于白色背景

方法解析:

- (void)startAnimating; 開(kāi)始動(dòng)畫(huà)

- (void)stopAnimating;  停止動(dòng)畫(huà)

- (BOOL)isAnimating;  是否正在運(yùn)行動(dòng)畫(huà)

3.UIDynamic

一、簡(jiǎn)單介紹
1.什么是UIDynamic
  • UIDynamic是從iOS 7開(kāi)始引入的一種新技術(shù),隸屬于UIKit框架

  • 可以認(rèn)為是一種物理引擎,能模擬和仿真現(xiàn)實(shí)生活中的物理現(xiàn)象。如:重力、彈性碰撞等現(xiàn)象

2.物理引擎的價(jià)值
  • 廣泛用于游戲開(kāi)發(fā),經(jīng)典成功案例是“憤怒的小鳥(niǎo)”

  • 讓開(kāi)發(fā)人員可以在遠(yuǎn)離物理學(xué)公式的情況下,實(shí)現(xiàn)炫酷的物理仿真效果

  • 提高了游戲開(kāi)發(fā)效率,產(chǎn)生更多優(yōu)秀好玩的物理仿真游戲

3.知名的2D物理引擎
  • Box2d

  • Chipmunk

二、使用步驟

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

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

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

  3. 將物理仿真行為添加到物理仿真器中,開(kāi)始仿真

三、相關(guān)說(shuō)明
1.三個(gè)概念

(1)誰(shuí)要進(jìn)行物理仿真?

物理仿真元素(Dynamic Item

(2)執(zhí)行怎樣的物理仿真效果?怎樣的動(dòng)畫(huà)效果?

物理仿真行為(Dynamic Behavior

(3)讓物理仿真元素執(zhí)行具體的物理仿真行為

物理仿真器(Dynamic Animator

2.物理仿真元素

注意:

  • 不是任何對(duì)象都能做物理仿真元素
  • 不是任何對(duì)象都能進(jìn)行物理仿真

物理仿真元素要素:

  • 任何遵守了UIDynamicItem協(xié)議的對(duì)象

  • UIView默認(rèn)已經(jīng)遵守了UIDynamicItem協(xié)議,因此任何UI控件都能做物理仿真

  • UICollectionViewLayoutAttributes類默認(rèn)也遵守UIDynamicItem協(xié)議

3.物理仿真行為

(1)UIDynamic提供了以下幾種物理仿真行為

  • UIGravityBehavior:重力行為

  • UICollisionBehavior:碰撞行為

  • UISnapBehavior:捕捉行為

  • UIPushBehavior:推動(dòng)行為

  • UIAttachmentBehavior:附著行為

  • UIDynamicItemBehavior:動(dòng)力元素行為

(2)物理仿真行為須知

  • 上述所有物理仿真行為都繼承自UIDynamicBehavior

  • 所有的UIDynamicBehavior都可以獨(dú)立進(jìn)行

  • 組合使用多種行為時(shí),可以實(shí)現(xiàn)一些比較復(fù)雜的效果

4. 物理仿真器

(1)物理仿真器須知

  • 它可以讓物理仿真元素執(zhí)行物理仿真行為

  • 它是UIDynamicAnimator類型的對(duì)象

(2)UIDynamicAnimator的初始化

  • - (instancetype)initWithReferenceView:(UIView *)view;

    view參數(shù):是一個(gè)參照視圖,表示物理仿真的范圍

5.物理仿真器的說(shuō)明

(1)UIDynamicAnimator的常見(jiàn)方法

- (void)addBehavior:(UIDynamicBehavior *)behavior;//添加1個(gè)物理仿真行為

- (void)removeBehavior:(UIDynamicBehavior *)behavior;//移除1個(gè)物理仿真行為

- (void)removeAllBehaviors;//移除之前添加過(guò)的所有物理仿真行為

(2)UIDynamicAnimator的常見(jiàn)屬性

@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;//代理對(duì)象(能監(jiān)聽(tīng)物理仿真器的仿真過(guò)程,比如開(kāi)始和結(jié)束)

詳情見(jiàn)DynamicAnimationDemo

================

二、Core Animation

什么是Animation(動(dòng)畫(huà)),簡(jiǎn)單點(diǎn)說(shuō)就是在一段時(shí)間內(nèi),顯示的內(nèi)容發(fā)生了變化.對(duì)CALayer來(lái)說(shuō)就是在一段時(shí)間內(nèi),其Animatable Property發(fā)生了變化.
這里涉及到兩個(gè)東西: 一是Layer(基類CALayer),一是Animation(基于CAAnimation). Animation作用于Layer.CALayer提供了接口用于給自己添加Animation.

Core Animation是一組非常強(qiáng)大的動(dòng)畫(huà)處理API,使用它能做出非常絢麗的動(dòng)畫(huà)效果,而且往往是事半功倍,使用它需要添加QuartzCore .framework和引入對(duì)應(yīng)的框架<QuartzCore/QuartzCore.h> .

開(kāi)發(fā)步驟:

1> 初始化一個(gè)動(dòng)畫(huà)對(duì)象(CAAnimation)并設(shè)置一些動(dòng)畫(huà)相關(guān)屬性.

2> 添加動(dòng)畫(huà)對(duì)象到層(CALayer)中,開(kāi)始執(zhí)行動(dòng)畫(huà).

Core Animation的動(dòng)畫(huà)執(zhí)行過(guò)程都是在后臺(tái)操作的,不會(huì)阻塞主線程.

1. CALayer

CALayer與UIView的關(guān)系

在iOS中,你能看得見(jiàn)摸得著的東西基本上都是UIView,比如一個(gè)按鈕、一個(gè)文本標(biāo)簽、一個(gè)文本輸入框、一個(gè)圖標(biāo)等等,這些都是UIView。

其實(shí)UIView之所以能顯示在屏幕上,完全是因?yàn)樗鼉?nèi)部的一個(gè)圖層:

  • 在創(chuàng)建UIView對(duì)象時(shí),UIView內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)圖層(即CALayer對(duì)象),通過(guò)UIView的layer屬性可以訪問(wèn)這個(gè)層。

    @property(nonatomic,readonly,strong) CALayer *layer;

當(dāng)UIView需要顯示到屏幕上時(shí),會(huì)調(diào)用drawRect:方法進(jìn)行繪圖,并且會(huì)將所有內(nèi)容繪制在自己的圖層上,繪圖完畢后,系統(tǒng)會(huì)將圖層拷貝到屏幕上,于是就完成了UIView的顯示。

換句話說(shuō),UIView本身不具備顯示的功能,是它內(nèi)部的層才有顯示功能。

因此,通過(guò)調(diào)節(jié)CALayer對(duì)象,可以很方便的調(diào)整UIView的一些外觀屬性。

  • 對(duì)比CALayer,UIView多了一個(gè)事件處理的功能。也就是說(shuō),CALayer不能處理用戶的觸摸事件,而UIView可以。所以,如果顯示出來(lái)的東西需要跟用戶進(jìn)行交互的話,用UIView;如果不需要跟用戶進(jìn)行交互,用UIView或者CALayer都可以。當(dāng)然,CALayer的性能會(huì)高一些,因?yàn)樗倭耸录幚淼墓δ埽虞p量級(jí)。

Layer的渲染架構(gòu)

Layer也和View一樣存在著一個(gè)層級(jí)樹(shù)狀結(jié)構(gòu),稱之為圖層樹(shù)(Layer Tree),直接創(chuàng)建的或者通過(guò)UIView獲得的(view.layer)用于顯示的圖層樹(shù),稱之為模型樹(shù)(Model Tree),模型樹(shù)的背后還存在兩份圖層樹(shù)的拷貝,一個(gè)是呈現(xiàn)樹(shù)(Presentation Tree),一個(gè)是渲染樹(shù)(Render Tree)。

呈現(xiàn)樹(shù)可以通過(guò)普通layer(其實(shí)就是模型樹(shù))的layer.presentationLayer獲得,而模型樹(shù)則可以通過(guò)modelLayer屬性獲得。

  • 模型樹(shù)的屬性在其被修改的時(shí)候就變成了新的值,這個(gè)是可以用代碼直接操控的部分;
  • 呈現(xiàn)樹(shù)的屬性值和動(dòng)畫(huà)運(yùn)行過(guò)程中界面上看到的是一致的;
  • 渲染樹(shù)是私有的,你無(wú)法訪問(wèn)到,渲染樹(shù)是對(duì)呈現(xiàn)樹(shù)的數(shù)據(jù)進(jìn)行渲染。

為了不阻塞主線程,渲染的過(guò)程是在單獨(dú)的進(jìn)程或線程中進(jìn)行的,所以你會(huì)發(fā)現(xiàn)Animation的動(dòng)畫(huà)并不會(huì)阻塞主線程.

隱式動(dòng)畫(huà)

根層與非根層:

每一個(gè)UIView內(nèi)部都默認(rèn)關(guān)聯(lián)著一個(gè)CALayer,我們可用稱這個(gè)Layer為Root Layer(根層)

所有的非Root Layer,也就是手動(dòng)創(chuàng)建的CALayer對(duì)象,都存在著隱式動(dòng)畫(huà)

當(dāng)對(duì)非Root Layer的部分屬性進(jìn)行修改時(shí),默認(rèn)會(huì)自動(dòng)產(chǎn)生一些動(dòng)畫(huà)效果,而這些屬性稱為Animatable Properties(可動(dòng)畫(huà)屬性)。

可以通過(guò)事務(wù)關(guān)閉隱式動(dòng)畫(huà):
CATransaction 是核心動(dòng)畫(huà)里面負(fù)責(zé)協(xié)調(diào)多個(gè)動(dòng)畫(huà)原子更新顯示操作。事務(wù)支持嵌套使用。
<pre><code>[CATransaction begin];
// 關(guān)閉隱式動(dòng)畫(huà)
[CATransaction setDisableActions:YES];

self.myview.layer.position = CGPointMake(10, 10);

[CATransaction commit];</code></pre>

CALayer的基本屬性

<pre><code>position和anchorPoint的作用
@property CGPoint position;

用來(lái)設(shè)置CALayer在父層中的位置
以父層的左上角為原點(diǎn)(0, 0)

@property CGPoint anchorPoint;

稱為“定位點(diǎn)”、“錨點(diǎn)”,
決定著CALayer身上的哪個(gè)點(diǎn)會(huì)在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),那么該層在父層中只會(huì)看到四分之一的部分。
</code></pre>
為了進(jìn)一步說(shuō)明anchorPoint的作用,假設(shè)有一個(gè)層大小100*100,現(xiàn)在中心點(diǎn)位置(50,50),由此可以得出frame(0,0,100,100)。上面說(shuō)過(guò)anchorPoint默認(rèn)為(0.5,0.5),同中心點(diǎn)position重合,此時(shí)使用圖形描述如圖1;當(dāng)修改anchorPoint為(0,0),此時(shí)錨點(diǎn)處于圖層左上角,但是中心點(diǎn)poition并不會(huì)改變,因此圖層會(huì)向右下角移動(dòng),如圖2;然后修改anchorPoint為(1,1,),position還是保持位置不變,錨點(diǎn)處于圖層右下角,此時(shí)圖層如圖3。


2.CAAnimation概述

當(dāng)需要對(duì)非Root Layer進(jìn)行動(dòng)畫(huà)或者需要對(duì)動(dòng)畫(huà)做更多自定義的行為的時(shí)候,就必須使用到顯式動(dòng)畫(huà)了,顯式動(dòng)畫(huà)的基類為CAAnimation,顯式動(dòng)畫(huà)不會(huì)改變?cè)搶傩缘闹?它只是用于動(dòng)畫(huà)顯示。

  • 采用了CAMediaTiming協(xié)議:可以調(diào)整時(shí)間,包括持續(xù)時(shí)間,速度,重復(fù)次數(shù),并且能設(shè)定圖層過(guò)渡;
  • 采用了CAAction協(xié)議:可以通過(guò)響應(yīng)動(dòng)作的方式來(lái)顯示動(dòng)畫(huà).

來(lái)看下CAAnimation的繼承體系

  • CAAnimation是個(gè)抽象類,不具備動(dòng)畫(huà)效果,必須用它的子類才有動(dòng)畫(huà)效果。

  • CAPropertyAnimation也是個(gè)抽象類,本身不具備動(dòng)畫(huà)效果,只有子類才有。

    CABasicAnimation和CAKeyframeAnimation:

CABasicAnimation基本動(dòng)畫(huà),做一些簡(jiǎn)單效果。
CAKeyframeAnimation關(guān)鍵幀動(dòng)畫(huà),做一些連續(xù)的流暢的動(dòng)畫(huà)。
  • CAAnimationGroup是個(gè)動(dòng)畫(huà)組,可以同時(shí)進(jìn)行縮放,旋轉(zhuǎn)(同時(shí)進(jìn)行多個(gè)動(dòng)畫(huà))。
  • CATransition是轉(zhuǎn)場(chǎng)動(dòng)畫(huà),界面之間跳轉(zhuǎn)(切換)都可以用轉(zhuǎn)場(chǎng)動(dòng)畫(huà)。
1)CAAnimation——簡(jiǎn)介

是所有動(dòng)畫(huà)對(duì)象的父類,負(fù)責(zé)控制動(dòng)畫(huà)的持續(xù)時(shí)間和速度,是個(gè)抽象類,不能直接使用,應(yīng)該使用它具體的子類。

基本屬性說(shuō)明:
  • duration:動(dòng)畫(huà)的持續(xù)時(shí)間

  • repeatCount:重復(fù)次數(shù),無(wú)限循環(huán)可以設(shè)置HUGE_VALF或者M(jìn)AXFLOAT

  • repeatDuration: 重復(fù)時(shí)間

  • removedOnCompletion:默認(rèn)為YES,代表動(dòng)畫(huà)執(zhí)行完畢后就從圖層上移除,圖形會(huì)恢復(fù)到動(dòng)畫(huà)執(zhí)行前的狀態(tài)。如果想讓圖層保持顯示動(dòng)畫(huà)執(zhí)行后的狀態(tài),那就設(shè)置為NO,不過(guò)還要設(shè)置fillMode為kCAFillModeForwards

  • fillMode: 決定當(dāng)前對(duì)象在非active時(shí)間段的行為。比如動(dòng)畫(huà)開(kāi)始之前或者動(dòng)畫(huà)結(jié)束之

    fillMode屬性的設(shè)置:

       kCAFillModeRemoved 這個(gè)是默認(rèn)值,也就是說(shuō)當(dāng)動(dòng)畫(huà)開(kāi)始前和動(dòng)畫(huà)結(jié)束后,動(dòng)畫(huà)對(duì)layer都沒(méi)有影響,動(dòng)畫(huà)結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài)
    
       kCAFillModeForwards 當(dāng)動(dòng)畫(huà)結(jié)束后,layer會(huì)一直保持著動(dòng)畫(huà)最后的狀態(tài)
    
       kCAFillModeBackwards 在動(dòng)畫(huà)開(kāi)始前,只需要將動(dòng)畫(huà)加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫(huà)的初始狀態(tài)并等待動(dòng)畫(huà)開(kāi)始。
    
       kCAFillModeBoth 這個(gè)其實(shí)就是上面兩個(gè)的合成.動(dòng)畫(huà)加入后開(kāi)始之前,layer便處于動(dòng)畫(huà)初始狀態(tài),動(dòng)畫(huà)結(jié)束后layer保持動(dòng)畫(huà)最后的狀態(tài)
    
  • beginTime: 可以用來(lái)設(shè)置動(dòng)畫(huà)延遲執(zhí)行時(shí)間,若想延遲2s,就設(shè)置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當(dāng)前時(shí)間

  • timingFunction: 速度控制函數(shù),控制動(dòng)畫(huà)運(yùn)行的節(jié)奏

    速度控制函數(shù)(CAMediaTimingFunction):

       kCAMediaTimingFunctionLinear(線性):勻速,給你一個(gè)相對(duì)靜態(tài)的感覺(jué)
    
       kCAMediaTimingFunctionEaseIn(漸進(jìn)):動(dòng)畫(huà)緩慢進(jìn)入,然后加速離開(kāi)
    
       kCAMediaTimingFunctionEaseOut(漸出):動(dòng)畫(huà)全速進(jìn)入,然后減速的到達(dá)目的地
    
       kCAMediaTimingFunctionEaseInEaseOut(漸進(jìn)漸出):動(dòng)畫(huà)緩慢的進(jìn)入,中間加速,然后減速的到達(dá)目的地。這個(gè)是默認(rèn)的動(dòng)畫(huà)行為>
    
  • delegate:動(dòng)畫(huà)代理

CAAnimation在分類中定義了代理方法

<pre><code>
@interface NSObject (CAAnimationDelegate)

/* Called when the animation begins its active duration. */
// 動(dòng)畫(huà)開(kāi)始時(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. */
    // 動(dòng)畫(huà)結(jié)束后調(diào)用
  • (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

@end</code></pre>

2)CAPropertyAnimation

是CAAnimation的子類,也是個(gè)抽象類,要想創(chuàng)建動(dòng)畫(huà)對(duì)象,應(yīng)該使用它的兩個(gè)子類:CABasicAnimationCAKeyframeAnimation

基本屬性說(shuō)明:
keyPath:    通過(guò)指定CALayer的一個(gè)屬性名稱為keyPath(NSString類型),并且對(duì)CALayer的這個(gè)屬性的值進(jìn)行修改,達(dá)到相應(yīng)的動(dòng)畫(huà)效果。比如,指定@“position”為keyPath,就修改CALayer的position屬性的值,以達(dá)到平移的動(dòng)畫(huà)效果
CABasicAnimation——基本動(dòng)畫(huà)

屬性說(shuō)明:

fromValue:  keyPath相應(yīng)屬性的初始值
toValue:    keyPath相應(yīng)屬性的結(jié)束值
byValue:    keyPath相應(yīng)屬性的改變值

動(dòng)畫(huà)過(guò)程說(shuō)明:

隨著動(dòng)畫(huà)的進(jìn)行,在長(zhǎng)度為duration的持續(xù)時(shí)間內(nèi),keyPath相應(yīng)屬性的值從fromValue漸漸地變?yōu)閠oValue。

keyPath內(nèi)容是CALayer的可動(dòng)畫(huà)Animatable屬性。

如果fillMode = kCAFillModeForwards同時(shí)removedOnComletion = NO,那么在動(dòng)畫(huà)執(zhí)行完畢后,圖層會(huì)保持顯示動(dòng)畫(huà)執(zhí)行后的狀態(tài)。但在實(shí)質(zhì)上,圖層的屬性值還是動(dòng)畫(huà)執(zhí)行前的初始值,并沒(méi)有真正被改變。

CAKeyframeAnimation——關(guān)鍵幀動(dòng)畫(huà)

關(guān)鍵幀動(dòng)畫(huà),也是CAPropertyAnimation的子類,與CABasicAnimation的區(qū)別是:

CABasicAnimation只能從一個(gè)數(shù)值(fromValue)變到另一個(gè)數(shù)值(toValue),而CAKeyframeAnimation會(huì)使用一個(gè)NSArray保存這些數(shù)值

CABasicAnimation可看做是只有2個(gè)關(guān)鍵幀的CAKeyframeAnimation

屬性說(shuō)明:

values: NSArray對(duì)象。里面的元素稱為“關(guān)鍵幀”(keyframe)。動(dòng)畫(huà)對(duì)象會(huì)在指定的時(shí)間(duration)內(nèi),依次顯示values數(shù)組中的每一個(gè)關(guān)鍵幀

path: 可以設(shè)置一個(gè)CGPathRef、CGMutablePathRef,讓圖層按照路徑軌跡移動(dòng)。path只對(duì)CALayer的anchorPoint和position起作用。如果設(shè)置了path,那么values將被忽略

keyTimes: 可以為對(duì)應(yīng)的關(guān)鍵幀指定對(duì)應(yīng)的時(shí)間點(diǎn),其取值范圍為0到1.0,keyTimes中的每一個(gè)時(shí)間值都對(duì)應(yīng)values中的每一幀。如果沒(méi)有設(shè)置keyTimes,各個(gè)關(guān)鍵幀的時(shí)間是平分的

3)CAAnimationGroup——?jiǎng)赢?huà)組

動(dòng)畫(huà)組,是CAAnimation的子類,可以保存一組動(dòng)畫(huà)對(duì)象,將CAAnimationGroup對(duì)象加入層后,組中所有動(dòng)畫(huà)對(duì)象可以同時(shí)并發(fā)運(yùn)行。

默認(rèn)情況下,一組動(dòng)畫(huà)對(duì)象是同時(shí)運(yùn)行的,也可以通過(guò)設(shè)置動(dòng)畫(huà)對(duì)象的beginTime屬性來(lái)更改動(dòng)畫(huà)的開(kāi)始時(shí)間。

屬性說(shuō)明:

animations: 用來(lái)保存一組動(dòng)畫(huà)對(duì)象的NSArray

4)CATransition——轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

CATransition是CAAnimation的子類,用于做轉(zhuǎn)場(chǎng)動(dòng)畫(huà),能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭?dòng)畫(huà)效果。iOS比Mac OS X的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)效果少一點(diǎn)。

UINavigationController就是通過(guò)CATransition實(shí)現(xiàn)了將控制器的視圖推入屏幕的動(dòng)畫(huà)效果。

屬性說(shuō)明:

type: 動(dòng)畫(huà)過(guò)渡類型

subtype: 動(dòng)畫(huà)過(guò)度方向

subtype

startProgress: 動(dòng)畫(huà)起點(diǎn)(在整體動(dòng)畫(huà)的百分比)

endProgress: 動(dòng)畫(huà)終點(diǎn)(在整體動(dòng)畫(huà)的百分比)

步驟

1.創(chuàng)建轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

2.設(shè)置轉(zhuǎn)場(chǎng)類型、子類型(可選)及其他屬性

3.設(shè)置轉(zhuǎn)場(chǎng)后的新視圖并添加動(dòng)畫(huà)到圖層

舉例
<pre><code>CATransition *anim = [CATransition animation];
anim.type = @"cube";
anim.subtype = kCATransitionFromBottom;
[view.layer addAnimation:anim forKey:nil];
</code></pre>

詳情見(jiàn)KKCoreAnimation&&SKBounceAnimation

3.補(bǔ)充

1)CASpringAnimation

iOS9才引入的動(dòng)畫(huà)類,它繼承于CABaseAnimation,用于制作彈簧動(dòng)畫(huà)

參數(shù)說(shuō)明

mass://質(zhì)量,影響圖層運(yùn)動(dòng)時(shí)的彈簧慣性,質(zhì)量越大,彈簧拉伸和壓縮的幅度越大,動(dòng)畫(huà)的速度變慢,并且波動(dòng)幅度變大

stiffness://剛度系數(shù)(勁度系數(shù)/彈性系數(shù)),剛度系數(shù)越大,形變產(chǎn)生的力就越大,運(yùn)動(dòng)越快

damping://阻尼系數(shù),阻止彈簧伸縮的系數(shù),阻尼系數(shù)越大,停止越快

initialVelocity://初始速率,動(dòng)畫(huà)視圖的初始速度大小
速率為正數(shù)時(shí),速度方向與運(yùn)動(dòng)方向一致,速率為負(fù)數(shù)時(shí),速度方向與運(yùn)動(dòng)方向相反

settlingDuration://結(jié)算時(shí)間 返回彈簧動(dòng)畫(huà)到停止時(shí)的估算時(shí)間,根據(jù)當(dāng)前的動(dòng)畫(huà)參數(shù)估算
通常彈簧動(dòng)畫(huà)的時(shí)間使用結(jié)算時(shí)間比較準(zhǔn)確

2)CAShapeLayer:

CAShapeLayer顧名思義,繼承于CALayer。 每個(gè)CAShapeLayer對(duì)象都代表著將要被渲染到屏幕上的一個(gè)任意的形狀(shape)。具體的形狀由其path(類型為CGPathRef)屬性指定。 普通的CALayer是矩形,所以需要frame屬性。CAShapeLayer初始化時(shí)也需要指定frame值,但 它本身沒(méi)有形狀,它的形狀來(lái)源于其屬性path 。CAShapeLayer有不同于CALayer的屬性,它從CALayer繼承而來(lái)的屬性在繪制時(shí)是不起作用的。

3)CADisplayLink

CADisplayLink是一個(gè)計(jì)時(shí)器,但是同NSTimer不同的是,CADisplayLink的刷新周期同屏幕完全一致。例如在iOS中屏幕刷新周期是60次/秒,CADisplayLink刷新周期同屏幕刷新一致也是60次/秒,這樣一來(lái)使用它完成的逐幀動(dòng)畫(huà)(又稱為“時(shí)鐘動(dòng)畫(huà)”)完全感覺(jué)不到動(dòng)畫(huà)的停滯情況。

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ì)循環(huán)調(diào)用目標(biāo)方法,在這個(gè)方法中更新視圖內(nèi)容就可以完成逐幀動(dòng)畫(huà)。

使用方法:
<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];
開(kāi)始和暫停
// 暫停
link.paused = YES;
// 開(kāi)始
link.paused = NO;
</code></pre>

三、FaceBook POP動(dòng)畫(huà)

1.工作機(jī)制

POP是一個(gè)在iOS與OS X上通用的極具擴(kuò)展性的動(dòng)畫(huà)引擎 它在基本的靜態(tài)動(dòng)畫(huà)的基礎(chǔ)上增加的彈簧動(dòng)畫(huà)與衰減動(dòng)畫(huà)。

使之能創(chuàng)造出更真實(shí)更具物理性的交互動(dòng)畫(huà) POP的API可以快速的與現(xiàn)有的ObjC代碼集成并可以作用于任意對(duì)象的任意屬性。

POP 本質(zhì)上是基于定時(shí)器的動(dòng)畫(huà)庫(kù),使用每秒 60 頻率的定時(shí)器,即時(shí)鐘頻率為 1/60 秒(為了匹配 iOS 顯示屏幀率),使得動(dòng)畫(huà)刷新繪制頻率與屏幕刷新頻率一致。很多這類動(dòng)畫(huà)庫(kù)都使用 CADisplayLink 做為一個(gè)回調(diào)源。

在計(jì)算機(jī)的世界里面,其實(shí)并不存在絕對(duì)連續(xù)的動(dòng)畫(huà),你所看到的屏幕上的動(dòng)畫(huà)本質(zhì)上都是離散的,只是在一秒的時(shí)間里面離散的幀多到一定的數(shù)量人眼就覺(jué)得是連續(xù)的了,在iOS中,最大的幀率是60幀每秒。 iOS提供了Core Animation框架,只需要開(kāi)發(fā)者提供關(guān)鍵幀信息,比如提供某個(gè)animatable屬性終點(diǎn)的關(guān)鍵幀信息,然后中間的值則通過(guò)一定的算法進(jìn)行插值計(jì)算,從而實(shí)現(xiàn)補(bǔ)間動(dòng)畫(huà)。 Core Aniamtion中進(jìn)行插值計(jì)算所依賴的時(shí)間曲線由CAMediaTimingFunction提供。 Pop Animation在使用上和Core Animation很相似,都涉及Animation對(duì)象以及Animation的載體的概念,不同的是Core Animation的載體只能是CALayer,而Pop Animation可以是任意基于NSObject的對(duì)象。當(dāng)然大多數(shù)情況Animation都是界面上顯示的可視的效果,所以動(dòng)畫(huà)執(zhí)行的載體一般都直接或者間接是UIView或者CALayer。

  • Pop Animation相比于Core Animation的優(yōu)點(diǎn)

      1. Pop Animation應(yīng)用于CALayer時(shí),在動(dòng)畫(huà)運(yùn)行的任何時(shí)刻,layer和其presentationLayer的相關(guān)屬性值始終保持一致,而Core Animation做不到。 
      2.Pop Animation可以應(yīng)用任何NSObject的對(duì)象,而Core Aniamtion必須是CALayer。
    

2.源碼結(jié)構(gòu):

代碼包括四個(gè)目錄:

Animations: 定義pop支持的動(dòng)畫(huà)類型,并抽像各種動(dòng)畫(huà)的低層數(shù)據(jù)結(jié)構(gòu)

Engine:組織動(dòng)化運(yùn)行的數(shù)據(jù)結(jié)構(gòu),核心是動(dòng)化管理者,還包括了動(dòng)畫(huà)引擎所需要的可動(dòng)畫(huà)屬性定義、動(dòng)畫(huà)追蹤等內(nèi)容

Utility: 封裝Engine中用到的各種功能,包括數(shù)值運(yùn)算,數(shù)據(jù)轉(zhuǎn)換,運(yùn)算等

WebCore: 這部分是蘋(píng)果公司的代碼,矩陣運(yùn)算和貝賽爾曲線的,用于底層運(yùn)算。

1)Animations

 POPAnimation :定義了動(dòng)畫(huà)基類POPAnimation
    私有變量:結(jié)構(gòu)體`_POPAnimationState` 紀(jì)錄動(dòng)畫(huà)狀態(tài),是實(shí)現(xiàn)動(dòng)畫(huà)最關(guān)鍵的屬性
    公有變量:name beginTime delegate tracer(動(dòng)畫(huà)追蹤,紀(jì)錄各種動(dòng)畫(huà)事件) ^completionBlock removedOnCompletion paused
繼承關(guān)系:
    
NSObject
 POPAnimation
     POPPropertyAnimation
          POPBasicAnimation
          POPDecayAnimation
          POPSpringAnimation
     POPCustomAnimation

 _POPAnimationState
    _POPPropertyAnimationState
        _POPBasicAnimationState
        _POPDecayAnimationState
        _POPSpringAnimationState

NSObject (POP)讓所有對(duì)象增加pop動(dòng)畫(huà)支持(增刪改查)通過(guò)POPAnimator進(jìn)行管理

2)Engine

POPAnimateableProperty 可動(dòng)畫(huà)的屬性,用于定義動(dòng)畫(huà)類型和動(dòng)畫(huà)時(shí)修改值
    POPStaticAnimatablePropertyState 結(jié)構(gòu)體紀(jì)錄了屬性名,readBlock,writeBlock,和域值

    POPStaticAnimatablePropertyState _staticStates[]  紀(jì)錄了所有可動(dòng)畫(huà)的屬性對(duì)應(yīng)的名稱,其中的writeblock功能是把二進(jìn)制數(shù)據(jù)寫(xiě)到對(duì)應(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對(duì)象轉(zhuǎn)換為vector

POPAnimationTracer 動(dòng)畫(huà)跟蹤 通過(guò)POPAnimationEvent來(lái)描述

POPAnimator 動(dòng)畫(huà)管理者,紀(jì)錄所有的動(dòng)畫(huà)事件(POPAnimatorItem,紀(jì)錄了動(dòng)畫(huà)作用到的對(duì)象、動(dòng)畫(huà)key、動(dòng)畫(huà)對(duì)象等信息),初始化是把CADisplayLink注冊(cè)到runloop里定時(shí)觸發(fā)render過(guò)程,進(jìn)行一幀動(dòng)畫(huà)渲染。她提供了add、remove等操作Animation集合的方法,并提供了Observer和delegate等事件函數(shù)
POPAnimator通過(guò)兩層(key,view)存儲(chǔ)動(dòng)畫(huà),(動(dòng)畫(huà)目標(biāo)對(duì)象,(動(dòng)畫(huà)key,動(dòng)畫(huà)對(duì)象))
具體每幀的渲染過(guò)程有兩步:1.renderTime,更新state的狀態(tài)。 2.updateAnimatable,把state的變化更新到obj的具體屬性上

3)Utility 各種工具類

POPAction: ActionDisabler和ActionEnabler  利用RAII暫停核心動(dòng)畫(huà)以ActionEnabler為例,創(chuàng)建ActionEnabler時(shí)停止動(dòng)畫(huà),銷毀時(shí)重新運(yùn)行動(dòng)畫(huà)

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)鍵方法說(shuō)明:
計(jì)算行列式的值:不列舉了,很枯燥,行列式計(jì)算的基本概念,從二階計(jì)算到三階再計(jì)算到四階。主要作用是引擎層對(duì)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)的自帶動(dòng)畫(huà)
方法說(shuō)明:
UnitBezier(double p1x, double p1y, double p2x, double p2y)//用兩個(gè)控制點(diǎn)的坐標(biāo)初始化曲線,
double sampleCurveX(double t)//通過(guò)參數(shù)t計(jì)算對(duì)應(yīng)的x值
double sampleCurveY(double t)//通過(guò)參數(shù)t計(jì)算對(duì)應(yīng)的y值
double sampleCurveDerivativeX(double t)
//epsilon表示一個(gè)小間距,相當(dāng)于數(shù)學(xué)計(jì)算里的dX,一般為全距離的1/1000,
//求解x對(duì)應(yīng)的t值,用到了函數(shù)sampleCurveDerivativeX
double solveCurveX(double x, double epsilon)
double solve(double x, double epsilon)//求解x對(duì)應(yīng)的y值,分為兩步算,1.由x計(jì)算t;2.由t計(jì)算y

3.動(dòng)畫(huà)執(zhí)行流程:

1)POPAnimator是單例對(duì)象,初始化對(duì)象實(shí)例時(shí)注冊(cè)把CADisplayLink到runloop,定時(shí)調(diào)用render,通過(guò)renderTime函數(shù)遍歷所有正在執(zhí)行的動(dòng)畫(huà),使動(dòng)畫(huà)進(jìn)行到下一幀,并刷新畫(huà)面,直到所有動(dòng)畫(huà)推進(jìn)完成。

2)動(dòng)畫(huà)狀態(tài)的推進(jìn)最終都是通過(guò)_POPAnimationState類和其子類的advance方法推進(jìn)的,advance更新時(shí)間戳,updateAnimatable方法把state的狀態(tài)變更到動(dòng)畫(huà)要作用的obj對(duì)象。

3)Spring、Decay、Basic 都有各自實(shí)現(xiàn)的advance函數(shù)計(jì)算,而Custom方式不同,他是通過(guò)一個(gè)POPCustomAnimationBlock類型的回調(diào)來(lái)就算這一幀的值的。

4.動(dòng)畫(huà)使用

1)POPBasicAnimation

基本動(dòng)畫(huà),接口方面和CABasicAniamtion很相似,使用可以提供初始值fromValue,這個(gè) 終點(diǎn)值toValue,動(dòng)畫(huà)時(shí)長(zhǎng)duration以及決定動(dòng)畫(huà)節(jié)奏的timingFunction。timingFunction直接使用的CAMediaTimingFunction,是使用一個(gè)橫向縱向都為一個(gè)單位的擁有兩個(gè)控制點(diǎn)的貝賽爾曲線來(lái)描述的,橫坐標(biāo)為時(shí)間,縱坐標(biāo)為動(dòng)畫(huà)進(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

彈簧動(dòng)畫(huà)是Bezier曲線無(wú)法表述的,所以無(wú)法使用PopBasicAniamtion來(lái)實(shí)現(xiàn)。PopSpringAnimation便是專門(mén)用來(lái)實(shí)現(xiàn)彈簧動(dòng)畫(huà)的。

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 彈簧速度,速度越快,動(dòng)畫(huà)時(shí)間越短 [0, 20],默認(rèn)為12,和springBounciness一起決定著彈簧動(dòng)畫(huà)的效果

  • dynamicsTension 彈簧的張力

  • dynamicsFriction 彈簧摩擦

  • dynamicsMass 質(zhì)量 。張力,摩擦,質(zhì)量這三者可以從更細(xì)的粒度上替代springBounciness和springSpeed控制彈簧動(dòng)畫(huà)的效果

3)PopDecayAnimation

基于Bezier曲線的timingFuntion同樣無(wú)法表述Decay Aniamtion,所以Pop就單獨(dú)實(shí)現(xiàn)了一個(gè) PopDecayAnimation,用于衰減動(dòng)畫(huà)。衰減動(dòng)畫(huà)一個(gè)很常見(jiàn)的地方就是 UIScrollView 滑動(dòng)松開(kāi)后的減速,這里就基于UIView實(shí)現(xiàn)一個(gè)自己的ScrollView,然后使用PopDecayAnimation實(shí)現(xiàn) 此代碼可以詳細(xì)參見(jiàn) KKScrollView 的實(shí)現(xiàn),當(dāng)滑動(dòng)手勢(shì)結(jié)束時(shí),根據(jù)結(jié)束的加速度,給衰減動(dòng)畫(huà)一個(gè)初始的velocity,用來(lái)決定衰減的時(shí)長(zhǎng)。

4)POPCustomAnimation

通過(guò)自定義block刷新動(dòng)畫(huà)幀,更靈活的方式

POPCustomAnimation 并不是基于POPPropertyAnimation的,它直接繼承自PopAnimation用于創(chuàng)建自定義動(dòng)畫(huà)用的,通過(guò)POPCustomAnimationBlock類型的block進(jìn)行初始化,

typedef BOOL (^POPCustomAnimationBlock)(id target, POPCustomAnimation *animation); 

此block會(huì)在界面的每一幀更新的時(shí)候被調(diào)用,創(chuàng)建者需要在block中根據(jù)當(dāng)前currentTime和elapsedTime來(lái)決定如何更新target的相關(guān)屬性,以實(shí)現(xiàn)特定的動(dòng)畫(huà)。當(dāng)你需要結(jié)束動(dòng)畫(huà)的時(shí)候就在block中返回NO,否則返回YES。

詳情見(jiàn)facebook-pop-sample&&POP-Handapp

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,746評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,666評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,477評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,960評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,200評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,726評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,617評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,807評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,049評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,425評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,674評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,432評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,769評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容

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