看到一篇好文章,就忍不住copy過(guò)來(lái)了。
原貼:http://www.cocoachina.com/ios/20170124/18617.html
一、基礎(chǔ)知識(shí)

CAAnimation.png
二、CABasicAnimation
1. 動(dòng)畫(huà)的屬性和解釋
[圖片上傳失敗...(image-e5ca53-1532506694864)]
2.屬性值的解釋
repeatCount : 如果在swift中需要一直不斷重復(fù):Float.infinity,OC:HUGE_VALF
timingFunction:

timingFunction.png
kCAMediaTimingFunctionLinear--在整個(gè)動(dòng)畫(huà)時(shí)間內(nèi)動(dòng)畫(huà)都是以一個(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)畫(huà)開(kāi)始時(shí)會(huì)較慢,之后動(dòng)畫(huà)會(huì)加速。一個(gè)慢慢加速然后突然停止的方法。對(duì)于之前提到的自由落體的例子來(lái)說(shuō)很適合,或者比如對(duì)準(zhǔn)一個(gè)目標(biāo)的導(dǎo)彈的發(fā)射。
kCAMediaTimingFunctionEaseOut:動(dòng)畫(huà)在開(kāi)始時(shí)會(huì)較快,之后動(dòng)畫(huà)速度減慢。它以一個(gè)全速開(kāi)始,然后慢慢減速停止。它有一個(gè)削弱的效果,應(yīng)用的場(chǎng)景比如一扇門慢慢地關(guān)上,而不是砰地一聲。
kCAMediaTimingFunctionEaseInEaseOut:動(dòng)畫(huà)在開(kāi)始和結(jié)束時(shí)速度較慢,中間時(shí)間段內(nèi)速度較快。創(chuàng)建了一個(gè)慢慢加速然后再慢慢減速的過(guò)程。這是現(xiàn)實(shí)世界大多數(shù)物體移動(dòng)的方式,也是大多數(shù)動(dòng)畫(huà)來(lái)說(shuō)最好的選擇。如果只可以用一種緩沖函數(shù)的話,那就必須是它了。那么你會(huì)疑惑為什么這不是默認(rèn)的選擇,實(shí)際上當(dāng)使用UIView的動(dòng)畫(huà)方法時(shí),他的確是默認(rèn)的,但當(dāng)創(chuàng)建CAAnimation的時(shí)候,就需要手動(dòng)設(shè)置它了。
kCAMediaTimingFunctionDefault:它和kCAMediaTimingFunctionEaseInEaseOut很類似,但是加速和減速的過(guò)程都稍微有些慢。它和kCAMediaTimingFunctionEaseInEaseOut的區(qū)別很難察覺(jué),可能是蘋(píng)果覺(jué)得它對(duì)于隱式動(dòng)畫(huà)來(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)畫(huà)用kCAMediaTimingFunctionDefault作為它們的計(jì)時(shí)方法)。
使用方法:
pathAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
- fillMode

fillMode.png
kCAFillModeForwards:動(dòng)畫(huà)開(kāi)始之后layer的狀態(tài)將保持在動(dòng)畫(huà)的最后一幀,而removedOnCompletion的默認(rèn)屬性值是 YES,所以為了使動(dòng)畫(huà)結(jié)束之后layer保持結(jié)束狀態(tài),應(yīng)將removedOnCompletion設(shè)置為NO。
kCAFillModeBackwards:將會(huì)立即執(zhí)行動(dòng)畫(huà)的第一幀,不論是否設(shè)置了 beginTime屬性。觀察發(fā)現(xiàn),設(shè)置該值,剛開(kāi)始視圖不見(jiàn),還不知道應(yīng)用在哪里。
kCAFillModeBoth:該值是 kCAFillModeForwards 和 kCAFillModeBackwards的組合狀態(tài)
kCAFillModeRemoved:動(dòng)畫(huà)將在設(shè)置的 beginTime 開(kāi)始執(zhí)行(如沒(méi)有設(shè)置beginTime屬性,則動(dòng)畫(huà)立即執(zhí)行),動(dòng)畫(huà)執(zhí)行完成后將會(huì)layer的改變恢復(fù)原狀。
3.使用心得
盡量不要設(shè)置removedOnCompletion = false ,因?yàn)榕浜螩AAnimationDelegate會(huì)帶來(lái)循環(huán)運(yùn)用的問(wèn)題,如果需要?jiǎng)赢?huà)停留在最后的狀態(tài),可以直接設(shè)置View的center屬性在動(dòng)畫(huà)結(jié)束的位置Point
之所以會(huì)出現(xiàn) 循環(huán)引用 因?yàn)橛捎贑AAnimation的delegate使用的strong類型:看一下簡(jiǎn)要的說(shuō)明圖:

CAAnimationDelegate.png
解決有時(shí)視圖會(huì)閃動(dòng)一下的問(wèn)題,我們可以將layer的屬性值設(shè)置為我們的動(dòng)畫(huà)最后要達(dá)到的值,然后再給我們的視圖添加layer動(dòng)畫(huà)。
4.樣例展示
- 旋轉(zhuǎn)動(dòng)畫(huà)
[圖片上傳失敗...(image-1f1ecb-1532506694864)]
旋轉(zhuǎn)動(dòng)畫(huà).gif
- 位移動(dòng)畫(huà)

位移動(dòng)畫(huà).gif
- 背景顏色變化動(dòng)畫(huà)、背景圖片變化動(dòng)畫(huà)、圓角變化動(dòng)畫(huà)

動(dòng)畫(huà)集合-1.gif
- 比例縮放動(dòng)畫(huà)

比例縮放動(dòng)畫(huà)-1.gif
- size大小縮放、透明值變化動(dòng)畫(huà)(可用作閃爍效果)

size大小縮放、透明值變化動(dòng)畫(huà).gif
5.常用KeyPath總結(jié)

三、CAKeyframeAnimation
CAKeyframeAnimation是核心動(dòng)畫(huà)里面的幀動(dòng)畫(huà),它提供了按照指定的一串值進(jìn)行動(dòng)畫(huà),好像拍電影一樣的一幀一幀的效果
1.屬性解釋
values: 是許多值組成的數(shù)組用來(lái)進(jìn)行動(dòng)畫(huà)的。這個(gè)屬性比較特別,只有在path屬性值為nil的時(shí)候才有作用
path:路徑,可以指定一個(gè)路徑,讓動(dòng)畫(huà)沿著這個(gè)指定的路徑執(zhí)行。
cacluationMode:在關(guān)鍵幀動(dòng)畫(huà)中還有一個(gè)非常重要的參數(shù),那便是calculationMode,計(jì)算模式.其主要針對(duì)的是每一幀的內(nèi)容為一個(gè)座標(biāo)點(diǎn)的情況,也就是對(duì)anchorPoint 和 position 進(jìn)行的動(dòng)畫(huà).當(dāng)在平面座標(biāo)系中有多個(gè)離散的點(diǎn)的時(shí)候,可以是離散的,也可以直線相連后進(jìn)行插值計(jì)算,也可以使用圓滑的曲線將他們相連后進(jìn)行插值計(jì)算.
1)kCAAnimationLinear calculationMode的默認(rèn)值,r自定義控制動(dòng)畫(huà)的時(shí)間(線性)可以設(shè)置keyTimes,表示當(dāng)關(guān)鍵幀為座標(biāo)點(diǎn)的時(shí)候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計(jì)算;
2)kCAAnimationDiscrete 離散的,就是不進(jìn)行插值計(jì)算,所有關(guān)鍵幀直接逐個(gè)進(jìn)行顯示;
3)kCAAnimationPaced 節(jié)奏動(dòng)畫(huà)自動(dòng)計(jì)算動(dòng)畫(huà)的運(yùn)動(dòng)時(shí)間,使得動(dòng)畫(huà)均勻進(jìn)行,而不是按keyTimes設(shè)置的或者按關(guān)鍵幀平分時(shí)間,此時(shí)keyTimes和timingFunctions無(wú)效;
4)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)畫(huà)需要設(shè)置timingFunctions
kCAAnimationCubicPaced 看這個(gè)名字就知道和kCAAnimationCubic有一定聯(lián)系,其實(shí)就是在kCAAnimationCubic的基礎(chǔ)上使得動(dòng)畫(huà)運(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)畫(huà)的分割時(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)畫(huà)中。keyTimes定義了應(yīng)用在每一關(guān)鍵幀的時(shí)間點(diǎn)。所有中間值的定時(shí)由定時(shí)函數(shù)控制,定時(shí)函數(shù)允許你對(duì)各個(gè)部分應(yīng)用緩入或緩出曲線定時(shí)。如果你不指定任何定時(shí)函數(shù),動(dòng)畫(huà)將會(huì)是線性的
rotationMode : 旋轉(zhuǎn)樣式
1)kCAAnimationRotateAuto 根據(jù)路徑自動(dòng)旋轉(zhuǎn)
2)kCAAnimationRotateAutoReverse 根據(jù)路徑自動(dòng)翻轉(zhuǎn)
2.樣例展示

CAKeyframeAnimation路徑動(dòng)畫(huà).gif
三、CATransition
主要用于轉(zhuǎn)場(chǎng)動(dòng)畫(huà)從一個(gè)場(chǎng)景以動(dòng)畫(huà)的形式過(guò)渡到另一個(gè)場(chǎng)景
1.屬性解釋
- type:轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的類型,一個(gè)自定義的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)中指定的過(guò)濾器屬性

另外還有一些系統(tǒng)未公開(kāi)的動(dòng)畫(huà)效果:
[``"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)畫(huà)將要去往的方向
startProgress、endProgress: 開(kāi)始和結(jié)束的位置進(jìn)度,數(shù)值介于[0,1]之間,結(jié)束值一定是大于開(kāi)始值的

3.動(dòng)畫(huà)樣例

CATransition路徑動(dòng)畫(huà).gif
四、CASpringAnimation
iOS9才引入的動(dòng)畫(huà)類,在以前我們都是使用facebook的pop來(lái)做這種彈簧效果,它繼承于CABaseAnimation,用于制作彈簧動(dòng)畫(huà)
1.參數(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.例子展示

CASpringAnimation彈簧動(dòng)畫(huà).gif
五、一些有意思的動(dòng)畫(huà)樣例
實(shí)現(xiàn)畫(huà)線過(guò)程的動(dòng)畫(huà),雖然很簡(jiǎn)單,但看到很多人都問(wèn)過(guò),效果如下:

drawLine動(dòng)畫(huà).gif
利用正弦曲線做的,效果還行,相信很多人都做過(guò):

water動(dòng)畫(huà).gif
左后奉上一個(gè)希望的小火苗,粒子動(dòng)畫(huà),效果很驚人,游戲用的比較多,有興趣,也可以研究下

fire動(dòng)畫(huà).gif
魚(yú)在魚(yú)池游動(dòng)的動(dòng)畫(huà)效果:

fish動(dòng)畫(huà).gif
最后的最后,奉上文章里部分例子的Demo地址:exampleForAnimation
簡(jiǎn)書(shū)不再更新,請(qǐng)移步掘進(jìn) https://juejin.cn/post/7207304028254421049