CAMediaTiming ( 時(shí)間協(xié)議)詳解
有一種通過(guò)CAAnimation實(shí)現(xiàn)的協(xié)議叫做CAMediaTiming,也就是CABasicAnimation和CAKeyframeAnimation的基類(指CAAnimation)。像duration,beginTime和repeatCount這些時(shí)間相關(guān)的屬性都在這個(gè)類中。大體而言,協(xié)議中定義了8個(gè)屬性,這些屬性通過(guò)一些方式結(jié)合在一起,準(zhǔn)確的控制著時(shí)間。文檔中每個(gè)屬性只有幾句話,所以很有可能在看這篇文章之前你都已經(jīng)讀過(guò)了,但是我覺(jué)得使用可視化的圖形能更好的解釋時(shí)間。
可視化的CAMediaTiming
為了顯示相關(guān)屬性的不同時(shí)間,無(wú)論是他們自己還是混合狀態(tài),我都會(huì)動(dòng)態(tài)的將橙色變?yōu)樗{(lán)色。下面的塊狀顯示了從開(kāi)始到結(jié)束的動(dòng)畫(huà)過(guò)程,時(shí)間線上每一個(gè)標(biāo)志代表一秒鐘。你可以看到時(shí)間線上的任意一點(diǎn),當(dāng)前顏色即表示動(dòng)畫(huà)中的當(dāng)前時(shí)間。比如,duration像下面一樣可視。
我們都知道,CALayer和CAAnimation都實(shí)現(xiàn)了CAMediaTiming 協(xié)議,因此在Core Animation中,理解CAMediaTiming協(xié)議中的屬性是非常必要的,但是蘋(píng)果的文檔中對(duì)于各個(gè)屬性描述太簡(jiǎn)單,對(duì)初學(xué)者容易理解,這篇文章主要幫助理解CAMediaTiming協(xié)議中各個(gè)屬性的含義。
CAMediaTiming Protocol提供了8個(gè)屬性,下面將分別講解。
CAMediaTiming / 時(shí)間協(xié)議
- repeatCount,動(dòng)畫(huà)的重復(fù)次數(shù),可以設(shè)置為小數(shù)。設(shè)置為HUGE_VALF,表示無(wú)限重復(fù)。
- repeatDuration,動(dòng)畫(huà)總時(shí)長(zhǎng),如果大于單次時(shí)長(zhǎng),則重復(fù);如果小于單次時(shí)長(zhǎng),則截?cái)唷?/li>
- duration,單次動(dòng)畫(huà)時(shí)長(zhǎng)。
- speed,圖層或動(dòng)畫(huà)模型相對(duì)于父圖層CALayer的時(shí)間流逝速度。
- fillMode,有效期結(jié)束后,動(dòng)畫(huà)對(duì)象的呈現(xiàn)效果是凍結(jié)還是移除。
- beginTime,相對(duì)于父對(duì)象的開(kāi)始時(shí)間。注意,以系統(tǒng)的絕對(duì)時(shí)間為準(zhǔn)。例如:
1
2
3
4
5
6
7
8
9
|
/** 當(dāng)前時(shí)間2秒以后開(kāi)始動(dòng)畫(huà) */ keyFrameAnim.beginTime = CACurrentMediaTime() + 2; /** 截止到當(dāng)前時(shí)間,動(dòng)畫(huà)已經(jīng)執(zhí)行了2秒, 注意,如果執(zhí)行的時(shí)間大于動(dòng)畫(huà)時(shí)長(zhǎng),則表示動(dòng)畫(huà)已經(jīng)執(zhí)行過(guò)。 */ keyFrameAnim.beginTime = CACurrentMediaTime() - 2; |
7.timeOffset,時(shí)間軸偏移量。將時(shí)間軸移動(dòng)至偏移位置,再執(zhí)行整個(gè)動(dòng)畫(huà)時(shí)長(zhǎng)。假設(shè)動(dòng)畫(huà)時(shí)長(zhǎng)3秒,偏移量為8,則開(kāi)始位置為8 % 3 = 2,再執(zhí)行3秒,即在整個(gè)時(shí)長(zhǎng)的1/ 3處結(jié)束。
8.CACurrentMediaTime,返回系統(tǒng)當(dāng)前的絕對(duì)時(shí)間(從本次開(kāi)機(jī)開(kāi)始),單位秒。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** The receiver does not appear until it begins and is removed from the presentation when it is completed. */ kCAFillModeRemoved; // (默認(rèn))動(dòng)畫(huà)模型的呈現(xiàn)效果直至開(kāi)始時(shí)才顯示,并在動(dòng)畫(huà)結(jié)束后移除。 /** The receiver does not appear until it begins but remains visible in its final state when it is completed. */ kCAFillModeForwards; // 動(dòng)畫(huà)模型的呈現(xiàn)效果直至開(kāi)始時(shí)才顯示,但在動(dòng)畫(huà)結(jié)束后仍然顯示最后的狀態(tài)。 /** The receiver appears in its initial state before it begins but is removed from the presentation when it is completed. */ kCAFillModeBackwards; // 動(dòng)畫(huà)開(kāi)始之前,動(dòng)畫(huà)模型顯示其初始呈現(xiàn)效果,但在動(dòng)畫(huà)結(jié)束后移除。 /** The receiver appears in its initial state before it begins and remains visible in its final state when it is completed. */ kCAFillModeBoth; // 動(dòng)畫(huà)開(kāi)始之前,動(dòng)畫(huà)模型顯示其初始呈現(xiàn)效果,并且在動(dòng)畫(huà)結(jié)束后仍然顯示最后的狀態(tài)。 |
暫停/繼續(xù)動(dòng)畫(huà)demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
- (IBAction)pauseBtnClicked:(id)sender { /** 判斷當(dāng)前圖層對(duì)象是否有針對(duì)postion屬性的動(dòng)畫(huà)效果 */ if ([self.layer.presentationLayer animationForKey:@ "position" ]) { // 通過(guò)絕對(duì)時(shí)間獲取圖層的本地時(shí)間 CFTimeInterval localTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil]; /** 將圖層的時(shí)間流逝速度設(shè)置為0,以暫停動(dòng)畫(huà) */ self.layer.speed = 0; // 設(shè)置圖層的時(shí)間軸偏移量,為繼續(xù)動(dòng)畫(huà)做準(zhǔn)備 self.layer.timeOffset = localTime; } } - (IBAction)continueBtnClicked:(id)sender { /** 判斷當(dāng)前圖層對(duì)象是否有針對(duì)postion屬性的動(dòng)畫(huà)效果 */ if ([self.layer.presentationLayer animationForKey:@ "position" ]) { // 獲取上次暫停時(shí)的時(shí)間軸偏移量 CFTimeInterval timeOffset = self.layer.timeOffset; // 重置時(shí)間軸偏移量 self.layer.timeOffset = 0; // 速度還原為1 self.layer.speed = 1; // 重置開(kāi)始時(shí)間 #warning 此處嚴(yán)重不理解。 self.layer.beginTime = 0; // 計(jì)算暫停時(shí)間和當(dāng)前時(shí)間的差值 CFTimeInterval localTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil]; CFTimeInterval timeSincePause = localTime - timeOffset; // 從上一次暫停處開(kāi)始 self.layer.beginTime = timeSincePause; } } |
感謝閱讀,希望能幫助到大家,謝謝大對(duì)本站的支持!
原文鏈接:http://www.jianshu.com/p/514a4960a080