轉(zhuǎn)自:iOS動(dòng)畫詳解
原博主寫的特別棒,在此收藏一遍以防丟失,供自己學(xué)習(xí)參考之用。
另,原文為Swift版本,本篇轉(zhuǎn)為Objective-C版本。
一、基礎(chǔ)知識(shí)

二、CABasicAnimation
1. 動(dòng)畫的屬性和解釋
| 屬性 | 解釋 |
|---|---|
| duration | 動(dòng)畫的持續(xù)時(shí)間 |
| repeatCount | 動(dòng)畫持續(xù)次數(shù) |
| repeatDuration | 設(shè)置動(dòng)畫的時(shí)間,在該時(shí)間內(nèi)動(dòng)畫一直執(zhí)行,不計(jì)次數(shù) |
| beginTime | 指定動(dòng)畫開(kāi)始的時(shí)間。從開(kāi)始延遲幾秒的話,設(shè)置為CACurrentMediaTime() + 秒數(shù) 的方式 |
| timingFunction | 設(shè)置動(dòng)畫的速度變化 |
| fillMode | 動(dòng)畫在開(kāi)始和結(jié)束時(shí)的動(dòng)作,默認(rèn)值是 kCAFillModeRemoved |
| autoreverses | 動(dòng)畫結(jié)束時(shí)是否執(zhí)行逆動(dòng)畫 |
| fromValue | 所改變屬性的起始值 |
| toValue | 所改變屬性的結(jié)束時(shí)的值 |
| byValue | 所改變屬性相同起始值的改變量 |
| keyPath | 可以指定keyPath為CALayer的屬性值,并對(duì)它的值進(jìn)行修改,以達(dá)到對(duì)應(yīng)的動(dòng)畫效果,需要注意的是部分屬性值是不支持動(dòng)畫效果的 |
以下是具有動(dòng)畫效果的keyPath:
//CATransform3D Key Paths : (example)transform.rotation.z
//rotation.x
//rotation.y
//rotation.z
//rotation 旋轉(zhuǎn)
//scale.x
//scale.y
//scale.z
//scale 縮放
//translation.x
//translation.y
//translation.z
//translation 平移
//CGPoint Key Paths : (example)position.x
//x
//y
//CGRect Key Paths : (example)bounds.size.width
//origin.x
//origin.y
//origin
//size.width
//size.height
//size
//opacity
//backgroundColor
//cornerRadius
//borderWidth
//contents
//Shadow Key Path:
//shadowColor
//shadowOffset
//shadowOpacity
//shadowRadius
2.屬性值的解釋
repeatCount:(一直重復(fù)的情況)
Swift:Float.infinity
OC:HUGE_VALF-
TimingFunction:
timingFunction.png
kCAMediaTimingFunctionLinear
,在整個(gè)動(dòng)畫時(shí)間內(nèi)動(dòng)畫都是以一個(gè)相同的速度來(lái)改變。也就是勻速運(yùn)動(dòng)。一個(gè)線性的計(jì)時(shí)函數(shù),同樣也是CAAnimation的timingFunction屬性為空時(shí)候的默認(rèn)函數(shù)。線性步調(diào)對(duì)于那些立即加速并且保持勻速到達(dá)終點(diǎn)的場(chǎng)景會(huì)有意義(例如射出槍膛的子彈)。
kCAMediaTimingFunctionEaseIn
動(dòng)畫開(kāi)始時(shí)會(huì)較慢,之后動(dòng)畫會(huì)加速。一個(gè)慢慢加速然后突然停止的方法。對(duì)于之前提到的自由落體的例子來(lái)說(shuō)很適合,或者比如對(duì)準(zhǔn)一個(gè)目標(biāo)的導(dǎo)彈的發(fā)射。
kCAMediaTimingFunctionEaseOut
動(dòng)畫在開(kāi)始時(shí)會(huì)較快,之后動(dòng)畫速度減慢。它以一個(gè)全速開(kāi)始,然后慢慢減速停止。它有一個(gè)削弱的效果,應(yīng)用的場(chǎng)景比如一扇門慢慢地關(guān)上,而不是砰地一聲。
kCAMediaTimingFunctionEaseInEaseOut
動(dòng)畫在開(kāi)始和結(jié)束時(shí)速度較慢,中間時(shí)間段內(nèi)速度較快。創(chuàng)建了一個(gè)慢慢加速然后再慢慢減速的過(guò)程。這是現(xiàn)實(shí)世界大多數(shù)物體移動(dòng)的方式,也是大多數(shù)動(dòng)畫來(lái)說(shuō)最好的選擇。如果只可以用一種緩沖函數(shù)的話,那就必須是它了。那么你會(huì)疑惑為什么這不是默認(rèn)的選擇,實(shí)際上當(dāng)使用UIView的動(dòng)畫方法時(shí),他的確是默認(rèn)的,但當(dāng)創(chuàng)建CAAnimation的時(shí)候,就需要手動(dòng)設(shè)置它了。
kCAMediaTimingFunctionDefault
它和kCAMediaTimingFunctionEaseInEaseOut很類似,但是加速和減速的過(guò)程都稍微有些慢。它和kCAMediaTimingFunctionEaseInEaseOut的區(qū)別很難察覺(jué),可能是蘋果覺(jué)得它對(duì)于隱式動(dòng)畫來(lái)說(shuō)更適合(然后對(duì)UIKit就改變了想法,而是使用kCAMediaTimingFunctionEaseInEaseOut作為默認(rèn)效果),雖然它的名字說(shuō)是默認(rèn)的,但還是要記住當(dāng)創(chuàng)建顯式的CAAnimation它并不是默認(rèn)選項(xiàng)(換句話說(shuō),默認(rèn)的圖層行為動(dòng)畫用kCAMediaTimingFunctionDefault作為它們的計(jì)時(shí)方法)。
使用方法:
moveAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
-
FillMode
fillMode.png
kCAFillModeForwards :
動(dòng)畫開(kāi)始之后layer的狀態(tài)將保持在動(dòng)畫的最后一幀,而removedOnCompletion的默認(rèn)屬性值是YES,所以為了使動(dòng)畫結(jié)束之后layer保持結(jié)束狀態(tài),應(yīng)將removedOnCompletion設(shè)置為NO。
kCAFillModeBackwards :
將會(huì)立即執(zhí)行動(dòng)畫的第一幀,不論是否設(shè)置了 beginTime屬性。觀察發(fā)現(xiàn),設(shè)置該值,剛開(kāi)始視圖不見(jiàn),還不知道應(yīng)用在哪里。
kCAFillModeBoth:
該值是 kCAFillModeForwards 和 kCAFillModeBackwards的組合狀態(tài)
kCAFillModeRemoved:
動(dòng)畫將在設(shè)置的 beginTime 開(kāi)始執(zhí)行(如沒(méi)有設(shè)置beginTime屬性,則動(dòng)畫立即執(zhí)行),動(dòng)畫執(zhí)行完成后將會(huì)layer的改變恢復(fù)原狀。
3.使用心得
盡量不要設(shè)置removedOnCompletion = false ,因?yàn)榕浜?code>CAAnimationDelegate會(huì)帶來(lái)循環(huán)運(yùn)用的問(wèn)題,如果需要?jiǎng)赢嬐A粼谧詈蟮臓顟B(tài),可以直接設(shè)置View的center屬性在動(dòng)畫結(jié)束的位置Point之所以會(huì)出現(xiàn) 循環(huán)引用 因?yàn)橛捎?code>CAAnimation的delegate使用的strong類型:看一下簡(jiǎn)要的說(shuō)明圖:

解決有時(shí)視圖會(huì)閃動(dòng)一下的問(wèn)題,我們可以將
layer的屬性值設(shè)置為我們的動(dòng)畫最后要達(dá)到的值,然后再給我們的視圖添加layer動(dòng)畫。
4.樣例展示
-
旋轉(zhuǎn)動(dòng)畫
旋轉(zhuǎn)動(dòng)畫.gif -
位移動(dòng)畫
位移動(dòng)畫.gif -
背景顏色變化動(dòng)畫、背景圖片變化動(dòng)畫、圓角變化動(dòng)畫
動(dòng)畫集合-1.gif -
比例縮放動(dòng)畫
比例縮放動(dòng)畫.gif -
size大小縮放、透明值變化動(dòng)畫(可用作閃爍效果)
size大小縮放、透明值變化動(dòng)畫.gif
5.常用KeyPath總結(jié)
| KeyPath值 | 說(shuō)明 | Objective-C | Swift 3.0 |
|---|---|---|---|
| transform.scale | 比例縮放 | @(0.8) | 0.8 |
| transform.scale.x | 縮放寬的比例 | @(0.8) | 0.8 |
| transform.scale.y | 縮放高的比例 | @(0.8) | 0.8 |
| transform.rotation.x | 圍繞x軸旋轉(zhuǎn) | @(2 * M_PI) | 2 * M_PI |
| transform.rotation.y | 圍繞y軸旋轉(zhuǎn) | @(2 * M_PI) | 2 * M_PI |
| transform.rotation.z | 圍繞z軸旋轉(zhuǎn) | @(2 * M_PI) | 2 * M_PI |
| backgroundColor | 背景顏色的變化 | (__bridge id _Nullable)([UIColor redColor].CGColor) | UIColor.red.cgColor |
| bounds | 大小縮放,中心不變 | [NSValue valueWithCGRect:CGRectMake(0, 0, 90, 30)] | NSValue(cgRect: CGRect(x: 0, y: 0, width: 90, height: 30)) |
| position | 位置(中心點(diǎn)的改變) | [NSValue valueWithCGPoint:CGPointMake(60, 240)] | NSValue(cgPoint: CGPoint(x: 60, y: 240)) |
| contents | 內(nèi)容,比如UIImageView的圖片 | ((__bridge id)[UIImage imageNamed:@"to.jpg"].CGImage) | UIImage(named: "to")?.cgImage |
| opacity | 透明度 | @(0.4) | 0.4 |
| contentsRect.size.width | 橫向拉伸縮放 | @(0.5) | 0.5 |
| contentsRect.size.height | 縱向拉伸縮放 | @(0.5) | 0.5 |
三、CAKeyframeAnimation
CAKeyframeAnimation是核心動(dòng)畫里面的幀動(dòng)畫,它提供了按照指定的一串值進(jìn)行動(dòng)畫,好像拍電影一樣的一幀一幀的效果。
1. 屬性解釋
values: 是許多值組成的數(shù)組用來(lái)進(jìn)行動(dòng)畫的。這個(gè)屬性比較特別,只有在
path屬性值為nil的時(shí)候才有作用path:路徑,可以指定一個(gè)路徑,讓動(dòng)畫沿著這個(gè)指定的路徑執(zhí)行。
cacluationMode:在關(guān)鍵幀動(dòng)畫中還有一個(gè)非常重要的參數(shù),那便是
calculationMode計(jì)算模式。其主要針對(duì)的是每一幀的內(nèi)容為一個(gè)座標(biāo)點(diǎn)的情況,也就是對(duì)anchorPoint和position進(jìn)行的動(dòng)畫。當(dāng)在平面座標(biāo)系中有多個(gè)離散的點(diǎn)的時(shí)候,可以是離散的,也可以直線相連后進(jìn)行插值計(jì)算,也可以使用圓滑的曲線將他們相連后進(jìn)行插值計(jì)算。
- kCAAnimationLinear calculationMode的默認(rèn)值,r自定義控制動(dòng)畫的時(shí)間(線性)可以設(shè)置
keyTimes,表示當(dāng)關(guān)鍵幀為座標(biāo)點(diǎn)的時(shí)候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計(jì)算; - kCAAnimationDiscrete 離散的,就是不進(jìn)行插值計(jì)算,所有關(guān)鍵幀直接逐個(gè)進(jìn)行顯示;
- kCAAnimationPaced 節(jié)奏動(dòng)畫自動(dòng)計(jì)算動(dòng)畫的運(yùn)動(dòng)時(shí)間,使得動(dòng)畫均勻進(jìn)行,而不是按
keyTimes設(shè)置的或者按關(guān)鍵幀平分時(shí)間,此時(shí)keyTimes和timingFunctions無(wú)效; - kCAAnimationCubic 對(duì)關(guān)鍵幀為座標(biāo)點(diǎn)的關(guān)鍵幀進(jìn)行圓滑曲線相連后插值計(jì)算,對(duì)于曲線的形狀還可以通過(guò)
tensionValues、continuityValues、biasValues來(lái)進(jìn)行調(diào)整自定義,這里的數(shù)學(xué)原理是Kochanek–Bartels spline,這里的主要目的是使得運(yùn)行的軌跡變得圓滑,曲線動(dòng)畫需要設(shè)置timingFunctions。 - kCAAnimationCubicPaced 看這個(gè)名字就知道和
kCAAnimationCubic有一定聯(lián)系,其實(shí)就是在kCAAnimationCubic的基礎(chǔ)上使得動(dòng)畫運(yùn)行變得均勻,就是系統(tǒng)時(shí)間內(nèi)運(yùn)動(dòng)的距離相同,此時(shí)keyTimes以及timingFunctions也是無(wú)效的。
keyTimes:一個(gè)包含若干
NSNumber對(duì)象值的數(shù)組,用來(lái)區(qū)分動(dòng)畫的分割時(shí)機(jī)。值得注意的是,這些NSNumber對(duì)象的浮點(diǎn)型值在0.0~1.0之間。里面的值后一個(gè)比前一個(gè)要大或者相等。最好的結(jié)果是這個(gè)數(shù)組中的值和values里面的值或者path控制的值對(duì)應(yīng),否則可能會(huì)出現(xiàn)不了你想要的結(jié)果。屬性為應(yīng)用在每一關(guān)鍵幀指定應(yīng)用到每一個(gè)關(guān)鍵幀上的計(jì)時(shí)器。該屬性只在calculationMode屬性被設(shè)置為kCAAnimationLinear,kCAAnimaitonDiscrete,kCAAnimationCubic時(shí)被使用。它不使用在節(jié)奏動(dòng)畫中。keyTimes定義了應(yīng)用在每一關(guān)鍵幀的時(shí)間點(diǎn)。所有中間值的定時(shí)由定時(shí)函數(shù)控制,定時(shí)函數(shù)允許你對(duì)各個(gè)部分應(yīng)用緩入或緩出曲線定時(shí)。如果你不指定任何定時(shí)函數(shù),動(dòng)畫將會(huì)是線性的。rotationMode:旋轉(zhuǎn)樣式
- kCAAnimationRotateAuto 根據(jù)路徑自動(dòng)旋轉(zhuǎn)
- kCAAnimationRotateAutoReverse 根據(jù)路徑自動(dòng)翻轉(zhuǎn)
2. 樣例展示

四、CATransition
主要用于轉(zhuǎn)場(chǎng)動(dòng)畫從一個(gè)場(chǎng)景以動(dòng)畫的形式過(guò)渡到另一個(gè)場(chǎng)景。
1. 屬性解釋
- type:轉(zhuǎn)場(chǎng)動(dòng)畫的類型,一個(gè)自定義的轉(zhuǎn)場(chǎng)動(dòng)畫中指定的過(guò)濾器屬性
| 系統(tǒng)公開(kāi)API | 效果說(shuō)明 | 是否支持方向 |
| ------------- |:-------------:| -----|
| kCATransitionFade | 淡出效果 | 是 |
| kCATransitionMoveIn | 新視圖移動(dòng)到舊視圖上 | 是 |
| kCATransitionPush | 新視圖推出舊視圖 | 是 |
| kCATransitionReveal | 移開(kāi)舊視圖顯示新視圖 | 是 |
另外還有一些系統(tǒng)未公開(kāi)的動(dòng)畫效果:
["cube", "suckEffect", "rippleEffect", "pageCurl", "pageUnCurl", "oglFlip", "cameraIrisHollowOpen", "cameraIrisHollowClose", "spewEffect","genieEffect","unGenieEffect","twist","tubey","swirl","charminUltra", "zoomyIn", "zoomyOut", "oglApplicationSuspend"]
效果,就不一一列舉了,可以看下效果圖
- subtype:轉(zhuǎn)場(chǎng)動(dòng)畫將要去往的方向。
- startProgress、endProgress: 開(kāi)始和結(jié)束的位置進(jìn)度,數(shù)值介于[0,1]之間,結(jié)束值一定是大于開(kāi)始值的。
| 動(dòng)畫子類型 | 說(shuō)明 |
|---|---|
| kCATransitionFromRight | 從右側(cè)轉(zhuǎn)場(chǎng) |
| kCATransitionFromLeft | 從左側(cè)轉(zhuǎn)場(chǎng) |
| kCATransitionFromTop | 從頂部轉(zhuǎn)場(chǎng) |
| kCATransitionFromBottom | 從底部轉(zhuǎn)場(chǎng)動(dòng)畫子類型 |
2. 動(dòng)畫樣例

五、CASpringAnimation
iOS9才引入的動(dòng)畫類,在以前我們都是使用facebook的pop來(lái)做這種彈簧效果,它繼承于CABaseAnimation,用于制作彈簧動(dòng)畫。
1. 參數(shù)說(shuō)明
- mass:質(zhì)量,影響圖層運(yùn)動(dòng)時(shí)的彈簧慣性,質(zhì)量越大,彈簧拉伸和壓縮的幅度越大,動(dòng)畫的速度變慢,并且波動(dòng)幅度變大。
- stiffness:剛度系數(shù)(勁度系數(shù)/彈性系數(shù)),剛度系數(shù)越大,形變產(chǎn)生的力就越大,運(yùn)動(dòng)越快。
- damping:阻尼系數(shù),阻止彈簧伸縮的系數(shù),阻尼系數(shù)越大,停止越快。
- initialVelocity:初始速率,動(dòng)畫視圖的初始速度大小速率為正數(shù)時(shí),速度方向與運(yùn)動(dòng)方向一致,速率為負(fù)數(shù)時(shí),速度方向與運(yùn)動(dòng)方向相反如果。
- settlingDuration:結(jié)算時(shí)間 返回彈簧動(dòng)畫到停止時(shí)的估算時(shí)間,根據(jù)當(dāng)前的動(dòng)畫參數(shù)估算通常彈簧動(dòng)畫的時(shí)間使用結(jié)算時(shí)間比較準(zhǔn)確。
2. 例子展示

六、組動(dòng)畫
動(dòng)畫組,是CAAnimation的子類,可以保存一組動(dòng)畫對(duì)象,將CAAnimationGroup對(duì)象加入圖層后,組中所有動(dòng)畫對(duì)象可以同時(shí)并發(fā)運(yùn)行。
1. 參數(shù)說(shuō)明
- animations屬性:用來(lái)保存一組動(dòng)畫對(duì)象的
NSArray
注意:默認(rèn)情況下,一組動(dòng)畫對(duì)象是同時(shí)運(yùn)行的,也 可以通過(guò)設(shè)置動(dòng)畫對(duì)象的beginTime屬性來(lái)更改動(dòng)畫的開(kāi)始時(shí)間。
2. 例子展示

七、一些有意思的動(dòng)畫樣例
-
實(shí)現(xiàn)畫線過(guò)程的動(dòng)畫,雖然很簡(jiǎn)單,但看到很多人都問(wèn)過(guò),效果如下:
drawLine動(dòng)畫.gif -
利用正弦曲線做的,效果還行,相信很多人都做過(guò):
water動(dòng)畫.gif -
左后奉上一個(gè)希望的小火苗,粒子動(dòng)畫,效果很驚人,游戲用的比較多,有興趣,也可以研究下:
fire動(dòng)畫.gif -
魚在魚池游動(dòng)的動(dòng)畫效果:
fish動(dòng)畫.gif
最后的最后,奉上文章里部分例子的Demo地址:ExamplesForAnimation










