一款Loading動畫的實現思路(四·完結篇)

感謝大家對前幾篇的支持,這一篇,我們一鼓作氣,把整個動畫完成。

慣例,為了方便第一次來的同學,我先貼一下動畫完成的效果圖:


實現階段4時,我們用了一種處理問題的方式,大約是這樣的:

描述問題,直到足夠清晰
把問題分解成一組小問題
利用經驗處理可以解決的問題
經驗無法解決的問題,我們去調研,調研結果會成為我們下次的經驗

階段5中,我們再應用一下這個方式(有疑惑的同學可以戳第三篇)。

先來看一下階段5的效果圖,
慣例,前幾個階段的動畫我們用灰色快速表示,當前階段使用彩色慢速表示,如圖:

階段5

看上去比階段4還要復雜,別急,我們來描述一下:

一開始圓是扁的,圓里面有一條粗線,粗線的頂部和圓的頂部連在一起,
漸漸恢復原狀,同時粗線漸漸變長,連到了圓的底部,與此同時,粗線的某處出現了兩條線,分別向左下、右下延伸,漸漸連到了圓上。

很粗糙,但基本上描述出了這個階段。

上文中我加黑了部分文字,這些文字很有標志性(有的平臺轉載時看不到加黑,可以戳原文查看)

“一開始”,指示出了本階段動畫的初始階段
“漸漸”,指示出了動畫
“同時”、“分別”,指示出了本階段中可以拆分出的子動畫

由此我們可以得到下面的描述:

初始:
圓:扁的
粗線:頂部和圓頂部連著,底部不連著
左下線:看不到
右下線:看不到

動畫:
圓:恢復到正常的形狀
粗線:變長
左下線:出現并變長
右下線:出現并變長

結束:
圓:正常的形狀
粗線:頂點、底點分別與圓的頂點、底點連著
左下線:起點在粗線上,終點在圓上
右下線:起點在粗線上,終點在圓上

和前面的描述相比,這個描述形式化了,雖然還比較粗略,但已經清晰的標明動畫被拆分成了4部分,各部分的初始及結束狀態也有了。

我們給4部分染上不同的顏色看一下:

階段5 多彩版

是不是比之前的清晰多了,
描述問題分解問題,到這里我們就完成了。

接下來就是思考動畫的方案了:

圓:階段4中是執行transform.scale.y動畫變扁了,本階段將transform恢復為CATransform3DIdentity就可以了;
粗線:階段4中是從無成長到一定長度,用的stroke方案(想了解stroke方案的同學請戳第二篇),這個階段就是繼續變長,沿用stroke方案就可以了;
左下線、右下線:本質是一樣,從無成長到一定長度,類比粗線可知,可以使用stroke方案;

這些方案都是以前的經驗,階段5可以不用調研了。

接下來就是找關鍵的節點值了:

對于一個動畫來講,關鍵的節點就是初始狀態和結束狀態,前幾篇中我們一起找過了關鍵的節點值,相信大家已經有感覺了,本文我們就不再找了。

我們一起來看一下階段5中特殊的地方:

前文中說到粗線時,我說的是繼續變長
繼續聽上去就有延續的意思,看上去,粗線兩個階段的動畫可以合并成一個。

回憶一下,階段4中粗線的path起點是圓未變形時的頂點,終點是圓未變形時的圓心,strokeEnd是從path起點逐漸stroke到path的終點,如下圖(灰色是path,藍色是stroke,SS、SE是初始,SS'、SE'是結束):


階段4 粗線

結合階段5,我們可以將path的終點修改為圓的底點,這樣一來,就將階段4的strokeEnd修改為從path的起點stroke到path的1/2處,如下圖:


新階段4 粗線

而階段5的strokeEnd就是在階段4的基礎上繼續stroke到path的終點,這樣兩個階段的動畫就合到一起了,如下圖:


階段5 粗線

有的同學可能會說,早知道是這樣,一開始就這樣寫就可以了。

這么說的是有道理的,有的人習慣這樣,先分階段考慮,再整體看一下各階段,該合并的合并,該修改的修改,方案成形,最后寫代碼,這是個很好的方式。

然而對我來說,階段性的成就感很重要,每當我看到一個階段的動畫在我眼前動起來,感覺都很爽,所以我還是習慣于逐個階段的實現,有需要時重構前面的階段,只要邏輯清晰,重構起來問題不大。

每個人都能找到最適合自己的方式,這本身就是一種樂趣。

好了,階段5我們聊了很多,后面的階段我們就簡要的說一下了。
從完整的效果圖可知,這個動畫是有成功和失敗兩個狀態的,因此我們分開來看。

成功狀態,從階段5到階段6_success:


階段6_success

描述一下:
圓變色
對號漸漸出現(stroke)

失敗狀態,先是從階段3直接到階段6_fail:


階段6_fail

描述一下:
圓變色
嘆號的上半部分漸漸出現(stroke)
嘆號的下半部分漸漸出現(stroke)

然后從階段6_fail到階段7_fail:


階段7_fail

描述一下:
嘆號繞圓心左右晃幾下(rotate)

階段7_fail要簡單的說一下:

在階段6_fail中,嘆號被拆分成了上下兩個layer,而在階段7_fail中兩者又是作為一個整體動的,我們要讓它們分別執行動畫么?

不是的,一個獨立的動畫應該只涉及一個對象,兩個layer有共同的superLayer,讓superLayer執行動畫就可以了,假如superLayer還有其他subLayer,不方便執行動畫,我們在兩個layer和superLayer中間插入一層專門執行動畫的layer就可以了。

到這里,我們的動畫就完成了,完整代碼請移步GitHub上的OneLoadingAnimation工程

在結束之前,我們簡單說一下階段1另一種思路(想看看階段1的同學請戳第一篇),這個思路更符合直覺,這個思路是受簡友YouXianMing第一篇中的評論啟發,感謝。

先回憶一下階段1的樣子:


階段1

描述一下:
圓從不完整漸漸變到完整(stroke)
圓在漸漸旋轉(rotate)

由此我們得出,一個圓同時執行stroke和rotate動畫就可以了,下面是示意代碼

// 不完整的示意代碼
- (void)doStep1 {
    // 不用自定義layer了
    self.arcToCircleLayer = [CAShapeLayer layer]; 

    // stroke動畫
    CABasicAnimation *ssAnima = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    CABasicAnimation *seAnima = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];

    // rotate動畫
    CABasicAnimation *rotateAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

    // 同時執行
    CAAnimationGroup *animation = [CAAnimationGroup animation];
    animation.animations = @[ssAnima, seAnima, rotateAnima];
}

是不是比第一篇的實現方式更清晰,
我們也可以看到,問題分解后,局部的優化也比較方便,
這部分的完整代碼我放到了工程的OneLoadingAnimationStep1Another目錄下。

有的同學還記得,我們這是一個簡化的版本,階段4中原動效中圓的不規則變形被我處理成了規則變形,
為了思路不被卡住,我選擇了暫時簡化,完成之后,我們可以再去優化

為了彌補這個缺憾,我會開一個外篇,專門聊一下圓不規則變形的實現,歡迎大家到時來捧場;

另,有簡友在簡信中提到了Swift,因此我寫了一個Swift版的實現,放在了工程的OneLoadingAnimationCompleteSwift目錄下,由于我的Swift水平不夠,代碼里還有坑,僅供參考。

本系列的主線到這就完結了,非常感謝大家的捧場!

完整代碼

請參考GitHub上OneLoadingAnimation工程

本系列的?傳送門

鳴謝及推薦

相關鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容

  • ?感謝大家對前兩篇的支持,在第一篇的評論中,簡友YouXianMing提出了更好的實現思路,同樣在評論中,原動效設...
    柯爛閱讀 5,602評論 22 73
  • 18- UIBezierPath官方API中文翻譯(待校對) ----------------- 華麗的分割線 -...
    醉臥欄桿聽雨聲閱讀 1,082評論 1 1
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,733評論 25 708
  • 清明 清明時節雨飄飄,祭祖焚香煙裊裊。 生前當須孝心盡,事后不必把紙燒。 人去物空方思起,已讓桃花笑彎腰。 縱燒金...
    生達成長規劃閱讀 319評論 0 1
  • 端午放了三天假,我壓根就沒出過門,整天窩宿舍腐爛發臭,因為我的人生格言就是我偶像咪蒙的人生格言,生命在于一動不動。...
    好萌66閱讀 243評論 0 0