感謝大家對(duì)前幾篇的支持涣脚,這一篇示辈,我們一鼓作氣,把整個(gè)動(dòng)畫(huà)完成遣蚀。
慣例矾麻,為了方便第一次來(lái)的同學(xué),我先貼一下動(dòng)畫(huà)完成的效果圖:
實(shí)現(xiàn)階段4時(shí)芭梯,我們用了一種處理問(wèn)題的方式险耀,大約是這樣的:
描述問(wèn)題,直到足夠清晰玖喘,
把問(wèn)題分解成一組小問(wèn)題甩牺,
利用經(jīng)驗(yàn)處理可以解決的問(wèn)題,
經(jīng)驗(yàn)無(wú)法解決的問(wèn)題累奈,我們?nèi)フ{(diào)研贬派,調(diào)研結(jié)果會(huì)成為我們下次的經(jīng)驗(yàn)。
階段5中澎媒,我們?cè)賾?yīng)用一下這個(gè)方式(有疑惑的同學(xué)可以戳第三篇)搞乏。
先來(lái)看一下階段5的效果圖,
慣例戒努,前幾個(gè)階段的動(dòng)畫(huà)我們用灰色快速表示请敦,當(dāng)前階段使用彩色慢速表示,如圖:
看上去比階段4還要復(fù)雜储玫,別急侍筛,我們來(lái)描述一下:
一開(kāi)始圓是扁的,圓里面有一條粗線缘缚,粗線的頂部和圓的頂部連在一起勾笆,
圓漸漸恢復(fù)原狀,同時(shí)粗線漸漸變長(zhǎng)桥滨,連到了圓的底部窝爪,與此同時(shí)弛车,粗線的某處出現(xiàn)了兩條線,分別向左下蒲每、右下延伸纷跛,漸漸連到了圓上。
很粗糙邀杏,但基本上描述出了這個(gè)階段贫奠。
上文中我加黑了部分文字,這些文字很有標(biāo)志性(有的平臺(tái)轉(zhuǎn)載時(shí)看不到加黑望蜡,可以戳原文查看)
“一開(kāi)始”唤崭,指示出了本階段動(dòng)畫(huà)的初始階段
“漸漸”,指示出了動(dòng)畫(huà)
“同時(shí)”脖律、“分別”谢肾,指示出了本階段中可以拆分出的子動(dòng)畫(huà)
由此我們可以得到下面的描述:
初始:
圓:扁的
粗線:頂部和圓頂部連著,底部不連著
左下線:看不到
右下線:看不到
動(dòng)畫(huà):
圓:恢復(fù)到正常的形狀
粗線:變長(zhǎng)
左下線:出現(xiàn)并變長(zhǎng)
右下線:出現(xiàn)并變長(zhǎng)
結(jié)束:
圓:正常的形狀
粗線:頂點(diǎn)小泉、底點(diǎn)分別與圓的頂點(diǎn)芦疏、底點(diǎn)連著
左下線:起點(diǎn)在粗線上,終點(diǎn)在圓上
右下線:起點(diǎn)在粗線上微姊,終點(diǎn)在圓上
和前面的描述相比酸茴,這個(gè)描述形式化了,雖然還比較粗略兢交,但已經(jīng)清晰的標(biāo)明動(dòng)畫(huà)被拆分成了4部分薪捍,各部分的初始及結(jié)束狀態(tài)也有了。
我們給4部分染上不同的顏色看一下:
是不是比之前的清晰多了魁淳,
描述問(wèn)題和分解問(wèn)題飘诗,到這里我們就完成了。
接下來(lái)就是思考動(dòng)畫(huà)的方案了:
圓:階段4中是執(zhí)行transform.scale.y動(dòng)畫(huà)變扁了界逛,本階段將transform恢復(fù)為CATransform3DIdentity就可以了昆稿;
粗線:階段4中是從無(wú)成長(zhǎng)到一定長(zhǎng)度,用的stroke方案(想了解stroke方案的同學(xué)請(qǐng)戳第二篇)息拜,這個(gè)階段就是繼續(xù)變長(zhǎng)溉潭,沿用stroke方案就可以了;
左下線少欺、右下線:本質(zhì)是一樣喳瓣,從無(wú)成長(zhǎng)到一定長(zhǎng)度,類比粗線可知赞别,可以使用stroke方案畏陕;
這些方案都是以前的經(jīng)驗(yàn),階段5可以不用調(diào)研了仿滔。
接下來(lái)就是找關(guān)鍵的節(jié)點(diǎn)值了:
對(duì)于一個(gè)動(dòng)畫(huà)來(lái)講惠毁,關(guān)鍵的節(jié)點(diǎn)就是初始狀態(tài)和結(jié)束狀態(tài)犹芹,前幾篇中我們一起找過(guò)了關(guān)鍵的節(jié)點(diǎn)值,相信大家已經(jīng)有感覺(jué)了鞠绰,本文我們就不再找了腰埂。
我們一起來(lái)看一下階段5中特殊的地方:
前文中說(shuō)到粗線時(shí),我說(shuō)的是繼續(xù)變長(zhǎng)
繼續(xù)聽(tīng)上去就有延續(xù)的意思蜈膨,看上去屿笼,粗線兩個(gè)階段的動(dòng)畫(huà)可以合并成一個(gè)。
回憶一下翁巍,階段4中粗線的path起點(diǎn)是圓未變形時(shí)的頂點(diǎn)驴一,終點(diǎn)是圓未變形時(shí)的圓心,strokeEnd是從path起點(diǎn)逐漸stroke到path的終點(diǎn)灶壶,如下圖(灰色是path蛔趴,藍(lán)色是stroke,SS例朱、SE是初始,SS'鱼蝉、SE'是結(jié)束):
結(jié)合階段5洒嗤,我們可以將path的終點(diǎn)修改為圓的底點(diǎn),這樣一來(lái)魁亦,就將階段4的strokeEnd修改為從path的起點(diǎn)stroke到path的1/2處渔隶,如下圖:
而階段5的strokeEnd就是在階段4的基礎(chǔ)上繼續(xù)stroke到path的終點(diǎn),這樣兩個(gè)階段的動(dòng)畫(huà)就合到一起了洁奈,如下圖:
有的同學(xué)可能會(huì)說(shuō)间唉,早知道是這樣,一開(kāi)始就這樣寫(xiě)就可以了利术。
這么說(shuō)的是有道理的呈野,有的人習(xí)慣這樣,先分階段考慮印叁,再整體看一下各階段被冒,該合并的合并,該修改的修改轮蜕,方案成形昨悼,最后寫(xiě)代碼,這是個(gè)很好的方式跃洛。
然而對(duì)我來(lái)說(shuō)率触,階段性的成就感很重要,每當(dāng)我看到一個(gè)階段的動(dòng)畫(huà)在我眼前動(dòng)起來(lái)汇竭,感覺(jué)都很爽葱蝗,所以我還是習(xí)慣于逐個(gè)階段的實(shí)現(xiàn)穴张,有需要時(shí)重構(gòu)前面的階段,只要邏輯清晰垒玲,重構(gòu)起來(lái)問(wèn)題不大陆馁。
每個(gè)人都能找到最適合自己的方式,這本身就是一種樂(lè)趣合愈。
好了叮贩,階段5我們聊了很多,后面的階段我們就簡(jiǎn)要的說(shuō)一下了佛析。
從完整的效果圖可知益老,這個(gè)動(dòng)畫(huà)是有成功和失敗兩個(gè)狀態(tài)的,因此我們分開(kāi)來(lái)看寸莫。
成功狀態(tài)捺萌,從階段5到階段6_success:
描述一下:
圓變色
對(duì)號(hào)漸漸出現(xiàn)(stroke)
失敗狀態(tài),先是從階段3直接到階段6_fail:
描述一下:
圓變色
嘆號(hào)的上半部分漸漸出現(xiàn)(stroke)
嘆號(hào)的下半部分漸漸出現(xiàn)(stroke)
然后從階段6_fail到階段7_fail:
描述一下:
嘆號(hào)繞圓心左右晃幾下(rotate)
階段7_fail要簡(jiǎn)單的說(shuō)一下:
在階段6_fail中膘茎,嘆號(hào)被拆分成了上下兩個(gè)layer桃纯,而在階段7_fail中兩者又是作為一個(gè)整體動(dòng)的,我們要讓它們分別執(zhí)行動(dòng)畫(huà)么披坏?
不是的态坦,一個(gè)獨(dú)立的動(dòng)畫(huà)應(yīng)該只涉及一個(gè)對(duì)象,兩個(gè)layer有共同的superLayer棒拂,讓superLayer執(zhí)行動(dòng)畫(huà)就可以了伞梯,假如superLayer還有其他subLayer,不方便執(zhí)行動(dòng)畫(huà)帚屉,我們?cè)趦蓚€(gè)layer和superLayer中間插入一層專門(mén)執(zhí)行動(dòng)畫(huà)的layer就可以了谜诫。
到這里,我們的動(dòng)畫(huà)就完成了攻旦,完整代碼請(qǐng)移步GitHub上的OneLoadingAnimation工程喻旷。
在結(jié)束之前,我們簡(jiǎn)單說(shuō)一下階段1另一種思路(想看看階段1的同學(xué)請(qǐng)戳第一篇)敬特,這個(gè)思路更符合直覺(jué)掰邢,這個(gè)思路是受簡(jiǎn)友YouXianMing在第一篇中的評(píng)論啟發(fā),感謝伟阔。
先回憶一下階段1的樣子:
描述一下:
圓從不完整漸漸變到完整(stroke)
圓在漸漸旋轉(zhuǎn)(rotate)
由此我們得出辣之,一個(gè)圓同時(shí)執(zhí)行stroke和rotate動(dòng)畫(huà)就可以了,下面是示意代碼
// 不完整的示意代碼
- (void)doStep1 {
// 不用自定義layer了
self.arcToCircleLayer = [CAShapeLayer layer];
// stroke動(dòng)畫(huà)
CABasicAnimation *ssAnima = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
CABasicAnimation *seAnima = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
// rotate動(dòng)畫(huà)
CABasicAnimation *rotateAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
// 同時(shí)執(zhí)行
CAAnimationGroup *animation = [CAAnimationGroup animation];
animation.animations = @[ssAnima, seAnima, rotateAnima];
}
是不是比第一篇的實(shí)現(xiàn)方式更清晰皱炉,
我們也可以看到怀估,問(wèn)題分解后,局部的優(yōu)化也比較方便,
這部分的完整代碼我放到了工程的OneLoadingAnimationStep1Another目錄下多搀。
有的同學(xué)還記得歧蕉,我們這是一個(gè)簡(jiǎn)化的版本,階段4中原動(dòng)效中圓的不規(guī)則變形被我處理成了規(guī)則變形康铭,
為了思路不被卡住惯退,我選擇了暫時(shí)簡(jiǎn)化,完成之后从藤,我們可以再去優(yōu)化催跪。
為了彌補(bǔ)這個(gè)缺憾,我會(huì)開(kāi)一個(gè)外篇夷野,專門(mén)聊一下圓不規(guī)則變形的實(shí)現(xiàn)懊蒸,歡迎大家到時(shí)來(lái)捧場(chǎng);
另悯搔,有簡(jiǎn)友在簡(jiǎn)信中提到了Swift骑丸,因此我寫(xiě)了一個(gè)Swift版的實(shí)現(xiàn),放在了工程的OneLoadingAnimationCompleteSwift目錄下妒貌,由于我的Swift水平不夠通危,代碼里還有坑,僅供參考灌曙。
本系列的主線到這就完結(jié)了黄鳍,非常感謝大家的捧場(chǎng)!
完整代碼
請(qǐng)參考GitHub上OneLoadingAnimation工程平匈。
本系列的?傳送門(mén)
- 一款Loading動(dòng)畫(huà)的實(shí)現(xiàn)思路(?一)
- 一款Loading動(dòng)畫(huà)的實(shí)現(xiàn)思路(二)
- 一款Loading動(dòng)畫(huà)的實(shí)現(xiàn)思路(三)
- 一款Loading動(dòng)畫(huà)的實(shí)現(xiàn)思路(四·完結(jié)篇)
- Loading動(dòng)畫(huà)外篇·圓的不規(guī)則變形
鳴謝及推薦
- 原動(dòng)效的設(shè)計(jì)者 moonjoin
- Kitten的A-GUIDE-TO-iOS-ANIMATION
- 喵神發(fā)起的objc中國(guó)的動(dòng)畫(huà)部分,都是很優(yōu)秀的譯文藏古,衷心為翻譯的同學(xué)點(diǎn)贊增炭。