
系列文章:
- 老司機(jī)帶你走進(jìn)Core Animation 之CAAnimation
- 老司機(jī)帶你走進(jìn)Core Animation 之CADisplayLink
- 老司機(jī)帶你走進(jìn)Core Animation 之幾種動(dòng)畫(huà)的簡(jiǎn)單應(yīng)用
- 老司機(jī)帶你走進(jìn)Core Animation 之CAShapeLayer和CATextLayer
- 老司機(jī)帶你走進(jìn)Core Animation 之圖層的透視、漸變及復(fù)制
- 老司機(jī)帶你走進(jìn)Core Animation 之粒子發(fā)射、TileLayer與異步繪制
之所以要寫(xiě)這幾種簡(jiǎn)單應(yīng)用呢,是為了幫大家擴(kuò)展一下思維,基于CAAnimation和CADisplayLink其實(shí)我們可以做到很多事情,不過(guò)我們都還是需要一個(gè)思路。有的時(shí)候可能,拿到一個(gè)效果,我們一眼就可以看出來(lái),哦,使用核心動(dòng)畫(huà)就可以搞定,然而真正上手的時(shí)候就會(huì)發(fā)現(xiàn),哦,沒(méi)有想象的那么簡(jiǎn)單,為什么我達(dá)到的效果不對(duì)呢?一般情況下有兩種可能,要么是思路不完整,要么是思路根本就不對(duì)。CAAnimation固然靈活,但要是使用方法不當(dāng)?shù)脑?,也?huì)事倍功半。所以呢,今天老司機(jī)就針對(duì)以下幾種情況來(lái)介紹截個(gè)動(dòng)畫(huà)的實(shí)現(xiàn)方式。(說(shuō)這么多其實(shí)就是因?yàn)檫@段時(shí)間一直研究這個(gè),的確也沒(méi)研究別的,哈哈哈)
在這篇文章中你會(huì)看到以下一些內(nèi)容:
iOS中GIF動(dòng)圖的播放的實(shí)現(xiàn)方式
iOS系統(tǒng)更新圖標(biāo)樣式的實(shí)現(xiàn)方式
自定義水波樣式的HUD的實(shí)現(xiàn)方式
接下來(lái)我們就對(duì)這三個(gè)內(nèi)容逐一進(jìn)行一下講解。
iOS中GIF動(dòng)圖的播放的實(shí)現(xiàn)方式
我們知道,在OC中展示靜態(tài)圖片我們是使用UIIamgeView的,然而UIImageView對(duì)GIF動(dòng)畫(huà)的展示卻并不友好。我知道你們一定會(huì)說(shuō)UIImageView不是有組動(dòng)畫(huà)么,老司機(jī)當(dāng)然知道有這個(gè)api,老司機(jī)最開(kāi)始也是用這個(gè)api,但是有的時(shí)候就會(huì)發(fā)現(xiàn)播放出的gif的節(jié)奏有可能會(huì)跟原圖不太一樣。這是為什么呢?原來(lái)這是因?yàn)镚IF文件的原因。我們知道,GIF其實(shí)就是由很多幀靜態(tài)圖片組成后連續(xù)播放組成的。重點(diǎn)就在于其實(shí)每一幀的時(shí)間是可以不一樣的。(雖然這樣的情況的確占少數(shù))其實(shí)這種情況還好一些,我們知道系統(tǒng)的組動(dòng)畫(huà)api是不支持動(dòng)畫(huà)的暫停與恢復(fù)的,而且當(dāng)圖片很多的時(shí)候也有很大的崩潰幾率,這是我們所不希望看見(jiàn)的,那么我們就開(kāi)始想自己寫(xiě)一個(gè)api讓他完美解決以上問(wèn)題?怎么做呢?
其實(shí)無(wú)非是UIImageView的圖片不斷切換,我自己加個(gè)定時(shí)器都可以。不過(guò)重要的還是一個(gè)思路。要想做到每一幀的時(shí)間可以不一樣長(zhǎng),我相信用定時(shí)器很難實(shí)現(xiàn)吧。這個(gè)時(shí)候,我們是否可以換個(gè)思路,記得CAAnimation中可以指定每種狀態(tài)時(shí)間的那個(gè)動(dòng)畫(huà)叫什么么還?對(duì)了,CAKeyframeAnimation。不記得了回頭看看這里的內(nèi)容。
既然我們使用CAKeyframeAnimation的話,動(dòng)畫(huà)的暫停與恢復(fù)我們自然可以控制,只要控制好內(nèi)存也就可以解決崩潰問(wèn)題,那么這就是我們的思路了。
有了思路就方便很多了,接下來(lái)我們只要去實(shí)現(xiàn)就好了。我記得以為偉大的程序猿曾經(jīng)說(shuō)過(guò):
程序員最不怕的就是如何實(shí)現(xiàn),不會(huì)就去網(wǎng)上找,最怕的就是沒(méi)網(wǎng)和沒(méi)思路。 ------老司機(jī)
大體思路:
解析GIF文件,獲取每一幀圖片及對(duì)應(yīng)時(shí)長(zhǎng)
構(gòu)建CAKeyframeAnimation動(dòng)畫(huà),以layer的contents屬性去展示圖片
就這么簡(jiǎn)單的兩步。
老司機(jī)這里就不上全部代碼了,上一些核心的代碼簡(jiǎn)單的展示一下如何實(shí)現(xiàn):

以上就是核心代碼,其實(shí)每一句的目的都很簡(jiǎn)單,可能有些函數(shù)沒(méi)用過(guò)大家自己簡(jiǎn)單查一下也就都明白了。然后老司機(jī)放一下自己寫(xiě)的UIImageView的GIF分類,大家可以直接拿去用,在這里:

iOS系統(tǒng)更新圖標(biāo)樣式的實(shí)現(xiàn)方式
這個(gè)只得是什么呢?就是iOS中APP更新的時(shí)候在ICON上不是有一個(gè)更新的動(dòng)畫(huà)么?像下面這個(gè)樣子:

這里我們就針對(duì)這個(gè)動(dòng)畫(huà)的實(shí)現(xiàn)方式進(jìn)行一下探討。
說(shuō)實(shí)話拿到這個(gè)需求老司機(jī)第一反應(yīng)是CABasicAnimation。因?yàn)槲覀冎肋@個(gè)不規(guī)則的形狀我們完全可以使用CAShapeLayer去繪制(關(guān)于CoreAnimation中CALayer的個(gè)個(gè)子類老司機(jī)會(huì)在接下來(lái)的博客中逐一跟新,敬請(qǐng)期待)。不同的path可以繪制出不同的形狀,而且path屬性又是animutable的。貌似輕松地很。然而真正寫(xiě)了一下老司機(jī)發(fā)現(xiàn)自己還是太天真了,CABasicAnimation是基于始末狀態(tài)的補(bǔ)間動(dòng)畫(huà),然而老司機(jī)又根本拿不準(zhǔn)他自動(dòng)補(bǔ)充的計(jì)算方式,所以寫(xiě)出來(lái)的動(dòng)畫(huà)跟預(yù)期的總是有一定的差距,老司機(jī)的思路層一度陷入僵局。后來(lái)老司機(jī)換了一個(gè)思路,既然用不了補(bǔ)間動(dòng)畫(huà),我就一幀一幀畫(huà)吧。這里就用到了CADisplayLink(不熟悉的小伙伴來(lái)這里補(bǔ)票)。
大體思路:
找出能代表動(dòng)畫(huà)中每一種狀態(tài)的path
使用CADisplayLink反復(fù)繪制
首先我們找一下這個(gè)路徑要如何表示:
這里沒(méi)有什么訣竅啊,高中數(shù)學(xué)啊,就是硬畫(huà)啊,直接上代碼

這里屬性和參數(shù)老司機(jī)解釋一下self.sRadius是中間非暫停狀態(tài)下的扇形半徑。參數(shù)percent是將要繪制的路徑的角度百分比,suspendR是大家能看到暫停狀態(tài)下是從中心不斷擴(kuò)大一個(gè)圓的,suspendR就是當(dāng)前正要繪制的那個(gè)圓的半徑(注意并不是那個(gè)圓最終要變成的半徑,而是當(dāng)前的)。通過(guò)這三個(gè)變量老司機(jī)就能畫(huà)出這個(gè)指示器各個(gè)狀態(tài)的路徑。(是不是很膩害,畢竟數(shù)學(xué)課代表,嘖嘖嘖)
這里重點(diǎn)講的是動(dòng)畫(huà)的繪制,calayer的繪制老司機(jī)會(huì)在接下來(lái)的博客里面慢慢介紹,本例中用到的中空的layer使用了兩種繪制方式,usesEvenOddFillRule和mask兩種,稍后放的demo里面會(huì)有具體代碼,大家看一下就好。
接下來(lái)就是使用CADisplayLink去一幀一幀繪制了,這也是上一期講過(guò)的內(nèi)容了,老司機(jī)也不廢話了,一切盡在demo吧:
自定義水波樣式的HUD的實(shí)現(xiàn)方式
閑的無(wú)聊寫(xiě)的一個(gè)效果,先看圖:

其實(shí)這個(gè)效果還挺有意思的,那么如何實(shí)現(xiàn)呢?
其實(shí)有了上面的鋪墊你應(yīng)該會(huì)馬上反映出兩種思路:CAAnimation動(dòng)畫(huà)或者一幀一幀繪制。
這里老司機(jī)說(shuō)一句,本質(zhì)上,如果補(bǔ)間動(dòng)畫(huà)能完成效果的話,盡量使用CAAnimation,不用一幀幀繪制,代碼量少了,cpu壓力也小點(diǎn)。但是一般情況寫(xiě)復(fù)雜的補(bǔ)間動(dòng)畫(huà)都畫(huà)不出來(lái),比如說(shuō)這個(gè)。
我們還是分析一下需求,首先我們需要一條浪線,其次這條浪線還要能漲高。我們可以通過(guò)改變正弦曲線的相位來(lái)使波浪左右擺動(dòng)起來(lái),改變正弦曲線k值改變波浪的高度。(事實(shí)上老司機(jī)使用的是三次貝塞爾曲線模擬的正弦曲線,效果相似,只不過(guò)OC中沒(méi)有正弦曲線的封裝,想繪制正弦曲線的話會(huì)增加很多計(jì)算量)。
思路都在那,這個(gè)路徑的繪制代碼比較多,我就不截圖了,也是在demo中大家看一下就好,一步一步思路都很清晰,還有老司機(jī)一向是注釋詳細(xì)的,你懂我~
恩,這次主要是想給大家提供一下思路的擴(kuò)展,畢竟學(xué)會(huì)了動(dòng)畫(huà)要會(huì)用才是正道。
另外,我還要推薦老司機(jī)出品的DWAnimation,幫你清爽的生成CALayer的屬性動(dòng)畫(huà),并且任意拼接,組合~

gitHub下載地址:DWAnimation
歡迎給我star哦~
恩,轉(zhuǎn)載記得注明出處哦~
如果你覺(jué)得本篇文章對(duì)你有幫助,麻煩你給我點(diǎn)個(gè)贊!
如果你就喜歡老司機(jī)這墨跡勁你再加個(gè)關(guān)注!
如果你愛(ài)上老司機(jī)了你也可以給我打賞!
但是就算你給我打賞我也只賣藝,不賣身。
