衆所周知,絢麗動畫效果是iOS系統的一大特色,經過UIView層封裝的動畫,基本能夠知足咱們應用開發的全部需求,但若須要更加自由的控制動畫的展現,咱們就須要使用CoreAnimation框架中的一些類與方法spring
Core Animation是iOS和OS X上圖形渲染和動畫的基礎結構,可用於爲視圖和應用程序的其餘可視元素設置動畫。Core Animation的實現邏輯是將大部分實際繪圖工做交給專用圖形硬件加速渲染,以實現高幀率和流暢的動畫,而不會給CPU帶來負擔並下降應用程序的速度。數組
下圖描述了CoreAnimation與UIKit框架的關係微信
Core Animation開發動畫的本質就是將CALayer中的內容轉化爲位圖從而供硬件操做,因此想熟練掌握動畫操做必須瞭解CALayer框架
CALayer跟UIView概念上很類似,一樣都是被層級管理樹管理的一些矩形塊,一樣能夠包含內容,管理子圖層,能夠作動畫和變換。可是最大的不一樣是UIView能夠處理用戶的交互,而CALayer是不可以響應事件的,即便它提供了一些判斷觸點是否在圖層範圍內的方法。每個UIView視圖內部都封裝了一個CALayer圖層,咱們經過UIView的layer屬性訪問這個圖層。其實對於UIView來講負責內容展現的就是它內部的CALayer,UIView只不過是將自身的展現任務交給了內部的CALayer完成,而它還肩負着一些其它的任務,好比說用戶的交互響應,提供一些Core Animation底層方法的高級接口等。函數
那爲何不把這些任務放在一個類中處理而是把他們做爲平行關係同時存在呢?很重要的緣由是要將職責分離,這樣能夠避免不少重複的代碼,因爲iOS平臺和MacOS平臺上用戶的交互方式有着本質的不一樣,在iOS系統中咱們使用的是UIKit和UIView,而在MacOS系統中咱們使用的是AppKit和NSView,因此在這種狀況下將展現部分分離出來會給蘋果的多平臺系統開發帶來便捷。動畫
@interface CALayer : NSObject <NSSecureCoding, CAMediaTiming> { @private struct _CALayerIvars { int32_t refcount; uint32_t magic; void *layer; #if TARGET_OS_MAC && !TARGET_RT_64_BIT void * _Nonnull unused1[8]; #endif } _attr; }
CALayer屬性:CALayer層的主要工做是管理您提供的視覺內容,圖層自己具備可設置的可視屬性,例如背景顏色,邊框和陰影。除了管理視覺內容以外,還保留有關其內容的幾何形狀的信息(例如其位置,大小和變換),用於在屏幕上呈現該內容。ui
接下來咱們將講解下Core Animation的CAAnimation、CAPropertyAnimation、CABasicAnimation、CAKeyframeAnimation、CASpringAnimation、CATransition、CAAnimationGroup
及他們之間的關係,其間也穿插了CALayer動畫運行的原理、Animation-KeyPath值、CATransaction事務類、檢測動畫的結束、暫停和恢復圖層的動畫
等內容url
CAAnimation是核心動畫的基類,不能直接使用,主要負責動畫的時間、速度等,自己實現了CAMediaTiming協議。spa
@interface CAAnimation : NSObject <NSSecureCoding, NSCopying, CAMediaTiming, CAAction> { @private void *_attr; uint32_t _flags; }
CAAnimation屬性 | 說明 |
---|---|
timingFunction | CAMediaTimingFunction速度控制函數,控制動畫運行的節奏 |
removedOnCompletion | 默認爲YES,表明動畫執行完畢後就從圖層上移除,圖形會恢復到動畫執行前的狀態。若是想讓圖層保持顯示動畫執行後的狀態,那就設置爲NO,不過還要設置fillMode爲kCAFillModeForwards |
delegate | 代理(animationDidStart、animationDidStop) |
ps:CAMediaTimingFunction介紹代理
kCAMediaTimingFunctionLinear(線性):勻速,給你一個相對靜態的感受 kCAMediaTimingFunctionEaseIn(漸進):動畫緩慢進入,而後加速離開 kCAMediaTimingFunctionEaseOut(漸出):動畫全速進入,而後減速的到達目的地 kCAMediaTimingFunctionEaseInEaseOut(漸進漸出):動畫緩慢的進入,中間加速,而後減速的到達目的地。這個是默認的動畫行爲。
像duration,beginTime、repeatCount、speed、timeOffset、repeatDuration、autoreverses
這些時間相關的屬性都在這個類中。協議中的這些屬性經過一些方式結合在一塊兒,準確的控制着時間。
CAMediaTiming屬性 | 說明 |
---|---|
beginTime | 指定動畫開始的時間。從開始延遲幾秒的話,設置爲【CACurrentMediaTime() + 秒數】 的方式 |
duration | 動畫的時長 |
speed | 動畫運行速度(若是把動畫的duration設置爲3秒,而speed設置爲2,動畫將會在1.5秒結束,由於它以兩倍速在執行) |
timeOffset | 結合一個暫停動畫(speed=0)一塊兒使用來控制動畫的「當前時間」。暫停的動畫將會在第一幀卡住,而後經過改變timeOffset來隨意控制動畫進程 |
repeatCount | 重複的次數。不停重複設置爲 HUGE_VALF |
repeatDuration | 設置動畫的時間。在該時間內動畫一直執行,不計次數。 |
autoreverses | 動畫結束時是否執行逆動畫,若是duration爲1s,則完成一次autoreverse就須要2s。 |
fillMode | CAMediaTimingFillMode枚舉 |
ps:CAMediaTimingFillMode介紹
kCAFillModeRemoved:這個是默認值,也就是說當動畫開始前和動畫結束後,動畫對layer都沒有影響,動畫結束後,layer會恢復到以前的狀態 kCAFillModeForwards:當動畫結束後,layer會一直保持着toValue的狀態 kCAFillModeBackwards:若是要讓動畫在開始以前(延遲的這段時間內)顯示fromValue的狀態 kCAFillModeBoth:這個其實就是上面兩個的合成.動畫加入後開始以前,layer便處於動畫初始狀態,動畫結束後layer保持動畫最後的狀態 注意必須配合animation.removeOnCompletion = NO才能達到以上效果
繼承自CAAnimation,不能直接使用,要想建立動畫對象,應該使用它的兩個子類:CABasicAnimation和CAKeyframeAnimation
You do not create instances of CAPropertyAnimation: to animate the properties of a Core Animation layer, create instance of the concrete subclasses CABasicAnimation or CAKeyframeAnimation.
CAPropertyAnimation屬性 | 說明 |
---|---|
keyPath | 經過指定CALayer的一個屬性名稱爲keyPath(NSString類型),而且對CALayer的這個屬性的值進行修改,達到相應的動畫效果。好比,指定@「position」爲keyPath,就修改CALayer的position屬性的值,以達到平移的動畫效果 |
CABasicAnimation是核心動畫類簇中的一個類,其父類是CAPropertyAnimation,其子類是CASpringAnimation,它的祖父是CAAnimation。它主要用於製做比較單一的動畫,例如,平移、縮放、旋轉、顏色漸變、邊框的值的變化等,也就是將layer的某個屬性值從一個值到另外一個值的變化
CABasicAnimation屬性 | 說明 |
---|---|
fromValue | 所改變屬性的起始值 |
toValue | 所改變屬性的結束時的值 |
byValue | 所改變屬性相同起始值的改變量 |
代碼以下
let baseAnim = CABasicAnimation(keyPath: "position") baseAnim.duration = 2; //開始的位置 baseAnim.fromValue = NSValue(cgPoint: (imgView?.layer.position)!) baseAnim.toValue = NSValue(cgPoint: CGPoint(x: 260, y: 260)) // baseAnim.isRemovedOnCompletion = false // baseAnim.fillMode = CAMediaTimingFillMode.forwards imgView?.layer.add(baseAnim, forKey: "baseAnim-position") imgView?.center = CGPoint(x: 260, y: 260)
如上面代碼所示,須要添加imgView?.center = CGPoint(x: 260, y: 260)
來防止防止動畫結束後回到初始狀態,網上還有另一種方法是 設置removedOnCompletion、fillMode兩個屬性
baseAnim.removedOnCompletion = NO; baseAnim.fillMode = kCAFillModeForwards;
可是這種方法會形成modelLayer沒有修改,_view1的實際座標點並無在所看到的位置,會產生一些問題
CALayer有兩個實例方法presentationLayer(簡稱P)和modelLayer(簡稱M),
/* presentationLayer * 返回一個layer的拷貝,若是有任何活動動畫時,包含當前狀態的全部layer屬性 * 其實是逼近當前狀態的近似值。 * 嘗試以任何方式修改返回的結果都是未定義的。 * 返回值的sublayers 、mask、superlayer是當前layer的這些屬性的presentationLayer */ - (nullable instancetype)presentationLayer; /* modelLayer * 對presentationLayer調用,返回當前模型值。 * 對非presentationLayer調用,返回自己。 * 在生成表示層的事務完成後調用此方法的結果未定義。 */ - (instancetype)modelLayer;
從中能夠看到P便是咱們看到的屏幕上展現的狀態,而M就是咱們設置完當即生效的真實狀態;打一個比方的話,P是個瞎子,只負責走路(繪製內容),而M是個瘸子,只負責看路(如何繪製)
CALayer動畫運行的原理:P會在每次屏幕刷新時更新狀態,當有動畫CAAnimation(簡稱A)加入時,P由動畫A控制進行繪製,當動畫A結束被移除時P則再去取M的狀態展現。可是因爲M沒有變化,因此動畫執行結束又會回到起點。若是想要P在動畫結束後就停在當前狀態而不回到M的狀態,咱們就須要給A設置兩個屬性,一個是A.removedOnCompletion = NO
;表示動畫結束後A依然影響着P,另外一個是A.fillMode = kCAFillModeForwards
,這兩行代碼將會讓A控制住P在動畫結束後保持不變,可是此時咱們的P和M不一樣步,咱們看到的P是toValue的狀態,而M則仍是本身原來的狀態。舉個栗子,咱們初始化一個view,它的狀態爲1,咱們給它的layer加個動畫,from是0,to是2,設置fillMode爲kCAFillModeForewards
,則動畫結束後P的狀態是2,M的狀態是1,這可能會致使一些問題出現。好比你點P所在的位置點不動,由於響應點擊的是M。因此咱們應該讓P和M同步,如上代碼imgView?.center = CGPoint(x: 260, y: 260)
須要提一點的是:對M賦值,不會影響P的顯示,當P想要顯示的時候,它已經被A控制了,並不會先閃現一下。
上面的動畫的KeyPath值咱們只使用了position,其實還有不少類型能夠設置,下面咱們列出了一些比較經常使用的
keyPath值 | 說明 | 值類型 |
---|---|---|
position | 移動位置 | CGPoint |
opacity | 透明度 | 0-1 |
bounds | 變大與位置 | CGRect |
bounds.size | 由小變大 | CGSize |
backgroundColor | 背景顏色 | CGColor |
cornerRadius | 漸變圓角 | 任意數值 |
borderWidth | 改變邊框border的大小((圖形周圍邊框,border默認爲黑色)) | 任意數值 |
contents | 改變layer內容(圖片)注意若是想要達到改變內容的動畫效果;首先在運行動畫以前定義好layer的contents contents | CGImage |
transform.scale | 縮放、放大 | 0.0-1.0 |
transform.rotation.x | 旋轉動畫(翻轉,沿着X軸) | M_PI*n |
transform.rotation.Y | 旋轉動畫(翻轉,沿着Y軸) | M_PI*n |
transform.rotation.Z | 旋轉動畫(翻轉,沿着Z軸) | M_PI*n |
transform.translation.x | 旋轉動畫(翻轉,沿着X軸) | 任意數值 |
transform.translation.y | 旋轉動畫(翻轉,沿着Y軸) | 任意數值 |
CABasicAnimation是將屬性從起始值更改成結束值,而CAKeyframeAnimation對象是容許你以線性或非線性的方式設置一組目標值的動畫。關鍵幀動畫由一組目標數據值和每一個值到達的時間組成。不但能夠簡單的只指定值數組和時間數組,還能夠按照路徑進行更改圖層的位置。動畫對象採用您指定的關鍵幀,並經過在給定時間段內從一個值插值到下一個值來構建動畫。
CAKeyframeAnimation屬性 | 說明 |
---|---|
values | 關鍵幀值表示動畫必須執行的值,此屬性中的值僅在path屬性的值爲nil時才使用。根據屬性的類型,您可能須要用NSValue對象的NSNumber包裝這個數組中的值。對於一些核心圖形數據類型,您可能還須要將它們轉換爲id,而後再將它們添加到數組中。將給定的關鍵幀值應用於該層的時間取決於動畫時間,由calculationMode、keyTimes和timingFunctions屬性控制。關鍵幀之間的值是使用插值建立的,除非將計算模式設置爲kcaanimation離散 |
path | 基於點的屬性的路徑,對於包含CGPoint數據類型的層屬性,您分配給該屬性的路徑對象定義了該屬性在動畫長度上的值。若是指定此屬性的值,則忽略值屬性中的任何數據 |
keyTimes | keyTimes的值與values中的值一一對應指定關鍵幀在動畫中的時間點,取值範圍爲[0,1]。當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的 |
timingFunctions | 一個可選的CAMediaTimingFunction對象數組,指定每一個關鍵幀之間的動畫緩衝效果 |
calculationMode | 關鍵幀間插值計算模式 |
rotationMode | 定義沿路徑動畫的對象是否旋轉以匹配路徑切線 |
ps:
timingFunctions:動畫緩衝效果
kCAMediaTimingFunctionLinear:線性起搏,使動畫在其持續時間內均勻地發生 kCAMediaTimingFunctionEaseIn:使一個動畫開始緩慢,而後加速,隨着它的進程 kCAMediaTimingFunctionEaseOut:使動畫快速開始,而後緩慢地進行 kCAMediaTimingFunctionEaseInEaseOut:使動畫開始緩慢,在其持續時間的中間加速,而後在完成以前再放慢速度 kCAMediaTimingFunctionDefault:默認,確保動畫的時間與大多數系統動畫的匹配
calculationMode:動畫計算方式
kCAAnimationLinear:默認差值 kCAAnimationDiscrete:逐幀顯示 kCAAnimationPaced:勻速 無視keyTimes和timingFunctions設置 kCAAnimationCubic:keyValue之間曲線平滑 可用 tensionValues,continuityValues,biasValues 調整 kCAAnimationCubicPaced:keyValue之間平滑差值 無視keyTimes
rotationMode:旋轉方式
kCAAnimationRotateAuto:自動 kCAAnimationRotateAutoReverse:自動翻轉 不設置則不旋轉
代碼一、用values屬性
//建立動畫對象 let keyAnim = CAKeyframeAnimation(keyPath: "position") //設置values keyAnim.values = [NSValue(cgPoint: CGPoint(x: 100, y: 200)), NSValue(cgPoint: CGPoint(x: 200, y: 200)), NSValue(cgPoint: CGPoint(x: 200, y: 300)), NSValue(cgPoint: CGPoint(x: 100, y: 300)), NSValue(cgPoint: CGPoint(x: 100, y: 400)), NSValue(cgPoint: CGPoint(x: 200, y: 500))] //重複次數 默認爲1 keyAnim.repeatCount = MAXFLOAT //設置是否原路返回 默認爲false keyAnim.autoreverses = true //設置移動速度,越小越快 keyAnim.duration = 4.0 keyAnim.isRemovedOnCompletion = false keyAnim.fillMode = .forwards keyAnim.timingFunctions = [CAMediaTimingFunction(name: .easeInEaseOut)] imgView?.layer.add(keyAnim, forKey: "keyAnim-Values")
代碼二、用path屬性
//建立動畫對象 let keyAnim = CAKeyframeAnimation(keyPath: "position") //建立一個CGPathRef對象,就是動畫的路線 let path = CGMutablePath() //自動沿着弧度移動 path.addEllipse(in: CGRect(x: 150, y: 200, width: 200, height: 100)) //設置開始位置 path.move(to: CGPoint(x: 100, y: 100)) //沿着直線移動 path.addLine(to: CGPoint(x: 200, y: 100)) path.addLine(to: CGPoint(x: 200, y: 200)) path.addLine(to: CGPoint(x: 100, y: 200)) path.addLine(to: CGPoint(x: 100, y: 300)) path.addLine(to: CGPoint(x: 200, y: 400)) //沿着曲線移動 path.addCurve(to: CGPoint(x: 50.0, y: 275.0), control1: CGPoint(x: 150.0, y: 275.0), control2: CGPoint(x: 70.0, y: 120.0)) path.addCurve(to: CGPoint(x: 150.0, y: 275.0), control1: CGPoint(x: 250.0, y: 275.0), control2: CGPoint(x: 90.0, y: 120.0)) path.addCurve(to: CGPoint(x: 250.0, y: 275.0), control1: CGPoint(x: 350.0, y: 275.0), control2: CGPoint(x: 110, y: 120.0)) path.addCurve(to: CGPoint(x: 350.0, y: 275.0), control1: CGPoint(x: 450.0, y: 275.0), control2: CGPoint(x: 130, y: 120.0)) keyAnim.path = path //重複次數 默認爲1 keyAnim.repeatCount = MAXFLOAT //設置是否原路返回 默認爲false keyAnim.autoreverses = true //設置移動速度,越小越快 keyAnim.duration = 4.0 keyAnim.isRemovedOnCompletion = false keyAnim.fillMode = .forwards keyAnim.timingFunctions = [CAMediaTimingFunction(name: .easeInEaseOut)] imgView?.layer.add(keyAnim, forKey: "keyAnim-Path")
iOS9新出的CASpringAnimation繼承於CABaseAnimation,是蘋果專門解決開發者關於彈簧動畫的這個需求而封裝的類
CASpringAnimation屬性 | 說明 |
---|---|
mass | 質量,影響圖層運動時的彈簧慣性,質量越大,彈簧拉伸和壓縮的幅度越大,默認值:1 |
stiffness | 剛度係數(勁度係數/彈性係數),剛度係數越大,形變產生的力就越大,運動越快。默認值: 100 |
damping | 阻尼係數,阻止彈簧伸縮的係數,阻尼係數越大,中止越快。默認值:10; |
initialVelocity | 初始速率,動畫視圖的初始速度大小。默認值:0;速率爲正數時,速度方向與運動方向一致,速率爲負數時,速度方向與運動方向相反; |
settlingDuration | 估算時間 返回彈簧動畫到中止時的估算時間,根據當前的動畫參數估算; |
代碼以下
let springAnim = CASpringAnimation(keyPath: "bounds") springAnim.toValue = NSValue(cgRect:CGRect(x: 200, y: 230, width: 140, height: 140)) //mass模擬的是質量,影響圖層運動時的彈簧慣性,質量越大,彈簧拉伸和壓縮的幅度越大 默認值:1 springAnim.mass = 5 //stiffness剛度係數(勁度係數/彈性係數),剛度係數越大,形變產生的力就越大,運動越快。默認值: 100 springAnim.stiffness = 80 //damping阻尼係數,阻止彈簧伸縮的係數,阻尼係數越大,中止越快。默認值:10; springAnim.damping = 8 //initialVelocity初始速率,動畫視圖的初始速度大小。默認值:0;速率爲正數時,速度方向與運動方向一致,速率爲負數時,速度方向與運動方向相反; springAnim.initialVelocity = 10 //估算時間 返回彈簧動畫到中止時的估算時間,根據當前的動畫參數估算; springAnim.duration = springAnim.settlingDuration imgView?.layer.add(springAnim, forKey: "springAnim")
CATransition是CAAnimation的子類,用於作轉場動畫,可以爲圖層提供移出屏幕和移入屏幕的動畫效果。
CATransition屬性 | 說明 |
---|---|
type | CATransitionType,動畫過渡類型 |
subtype | CATransitionSubtype,動畫移動方向 |
startProgress | 動畫起點(在總體動畫的百分比) |
endProgress | 動畫終點(在總體動畫的百分比) |
ps:若是不須要動畫執行整個過程(動畫執行到中間部分就中止),能夠指定startProgress,endProgress屬性。
CATransitionType:動畫過渡類型
kCATransitionFade:漸變 kCATransitionMoveIn:覆蓋 kCATransitionPush:推出 kCATransitionReveal:揭開
除此以外,還支持如下私有方法
cube:立方體旋轉 suckEffect:吮吸 oglFlip:翻轉 rippleEffect:水波動畫 pageCurl:翻頁 pageUnCurl:反翻頁 cemeraIrisHollowOpen:開鏡頭 cameraIrisHollowClose:關鏡頭
CATransitionSubtype:控制動畫方向,上/下/左/右 4個不一樣方向的動畫
kCATransitionFromRight kCATransitionFromLeft kCATransitionFromTop kCATransitionFromBottom
單一的動畫並不能知足某些特定需求,這時就須要用到CAAnimationGroup,其是CAAnimation的子類,默認狀況下,一組動畫對象是同時運行的,也能夠經過設置動畫對象的beginTime屬性來更改動畫的時間
CATransition屬性 | 說明 |
---|---|
animations | [CAAnimation],動畫組 |
代碼以下
let groupAnim = CAAnimationGroup() //建立keyAnim let keyAnim = CAKeyframeAnimation(keyPath: "position") //設置values keyAnim.values = [NSValue(cgPoint: CGPoint(x: 100, y: 200)), NSValue(cgPoint: CGPoint(x: 200, y: 200)), NSValue(cgPoint: CGPoint(x: 200, y: 300)), NSValue(cgPoint: CGPoint(x: 100, y: 300)), NSValue(cgPoint: CGPoint(x: 100, y: 400)), NSValue(cgPoint: CGPoint(x: 200, y: 500))] keyAnim.duration = 4.0 keyAnim.timingFunctions = [CAMediaTimingFunction(name: .easeInEaseOut)] //建立漸變圓角 let animation = CABasicAnimation(keyPath: "cornerRadius") animation.toValue = 40 animation.duration = 4.0 imgView?.layer.masksToBounds = true groupAnim.animations = [keyAnim, animation] groupAnim.duration = 4.0 groupAnim.repeatCount = MAXFLOAT groupAnim.autoreverses = true imgView?.layer.add(groupAnim, forKey: "groupAnim")
將動畫分組在一塊兒的更高級方法是使用事務對象。經過容許您建立嵌套的動畫集併爲每一個動畫分配不一樣的動畫參數,事務提供了更大的靈活性。
CATransaction事務類能夠對多個layer的屬性同時進行修改,它分隱式事務,和顯式事務。 當咱們向圖層添加顯式或隱式動畫時,Core Animation都會自動建立隱式事務。可是,咱們還能夠建立顯式事務以更精確地管理這些動畫。
隱式事務
//建立layer let layer = CALayer() layer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) layer.position = CGPoint(x: 100, y: 350) layer.backgroundColor = UIColor.red.cgColor layer.borderColor = UIColor.black.cgColor layer.opacity = 1.0 view.layer.addSublayer(layer) //觸發動畫 // 設置變化動畫過程是否顯示,默認爲true不顯示 CATransaction.setDisableActions(false) layer.cornerRadius = (layer.cornerRadius == 0.0) ? 30.0 : 0.0 layer.opacity = (layer.opacity == 1.0) ? 0.5 : 1.0
顯式事務:經過明確的調用begin,commit來提交動畫
CATransaction.begin() layer.zPosition = 200.0 layer.opacity = 0.0 CATransaction.commit()
使用事務的主要緣由之一是在顯式事務的範圍內,咱們能夠更改持續時間,計時功能和其餘參數。還能夠爲整個事務分配完成塊,以便在動畫組完成時通知應用。
例如,將動畫的默認持續時間更改成8秒,使用setValue:forKey:
方法進行修改,目前支持的屬性包括: "animationDuration", "animationTimingFunction","completionBlock", "disableActions"
.
CATransaction.begin() CATransaction.setValue(8.0, forKey: "animationDuration") //執行動畫 CATransaction.commit()
嵌套事務: 當咱們要爲不一樣動畫集提供不一樣默認值的狀況下可使用嵌套事務。要將一個事務嵌套在另外一個事務中,只需再次調用begin,且每一個begin調用必須一一對應一個commit方法。只有在爲最外層事務提交更改後,Core Animation纔會開始關聯的動畫。
嵌套顯式事務代碼
//事務嵌套 CATransaction.begin() // 外部transaction CATransaction.setValue(2.0, forKey: "animationDuration") layer.position = CGPoint(x: 140, y: 140) CATransaction.begin() // 內部transaction CATransaction.setValue(5.0, forKey: "animationDuration") layer.zPosition = 200.0 layer.opacity = 0.0 CATransaction.commit() // 內部transaction CATransaction.commit() // 外部transaction
核心動畫支持檢測動畫開始或結束的時間。這些通知是進行與動畫相關的任何內務處理任務的好時機。例如,您可使用開始通知來設置一些相關的狀態信息,並使用相應的結束通知來拆除該狀態。
有兩種不一樣的方式能夠通知動畫的狀態:
setCompletionBlock:
方法將完成塊添加到當前事務。當事務中的全部動畫完成後,事務將執行完成塊。animationDidStart:
和animationDidStop:finished:
委託方法。若是要讓兩個動畫連接在一塊兒,以便在另外一個完成時啓動,請不要使用動畫通知。而是使用動畫對象的beginTime
屬性按照所需的時間啓動每一個動畫對象。將兩個動畫連接在一塊兒,只需將第二個動畫的開始時間設置爲第一個動畫的結束時間。
每一個圖層都有本身的本地時間,用於管理動畫計時。一般,兩個不一樣層的本地時間足夠接近,您能夠爲每一個層指定相同的時間值,用戶可能不會注意到任何內容。可是因爲superLayer或其自己Layer的時序參數設置,層的本地時間會發生變化。例如,更改Layer的speed
屬性會致使該Layer(及其子Layer)上的動畫持續時間按比例更改。
爲了確保Layer的時間值合適,CALayer類定義了convertTime:fromLayer:
和convertTime:toLayer:
方法。咱們可使用這些方法將固定時間值轉換爲Layer的本地時間或將時間值從一個Layer轉換爲另外一個Layer。這些方法可能影響圖層本地時間的媒體計時屬性,並返回可與其餘圖層一塊兒使用的值。
可以使用下面示例來獲取圖層的當前本地時間。CACurrentMediaTime函數返回計算機的當前時鐘時間,該方法將本機時間並轉換爲圖層的本地時間。
獲取圖層的當前本地時間
CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime()fromLayer:nil];
在圖層的本地時間中有時間值後,可使用該值更新動畫對象或圖層的與時序相關的屬性。使用這些計時屬性,您能夠實現一些有趣的動畫行爲,包括:
- (void)pauseLayer:(CALayer *)layer { CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime()fromLayer:nil]; layer.speed = 0.0; layer.timeOffset = pausedTime; } - (void)resumeLayer:(CALayer *)layer { CFTimeInterval pausedTime = [layer timeOffset]; layer.speed = 1.0; layer.timeOffset = 0.0; layer.beginTime = 0.0; CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime()fromLayer:nil] - pausedTime; layer.beginTime = timeSincePause; }
iOSSir公衆號技術交流微信羣!
須要進羣能夠添加公衆號助理「kele22558!」
![]()