你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 一款Loading動畫的實現思路(三)

一款Loading動畫的實現思路(三)

編輯:IOS開發基礎

感謝大家對前兩篇的支持,在第一篇的評論中,簡友YouXianMing提出了更好的實現思路,同樣在評論中,原動效設計者 moonjoin親自現身捧場,非常感謝!這也說明以分享來拋磚引玉是有效果的。

慣例,為了讓第一次來的同學對本系列有所了解,我先貼一下完整的效果圖,有興趣的同學,請移步本系列第一篇,可以的話請多提提建議,非常感謝,以下是效果圖

不多說了,我們開始第三篇。

1013170-9536a251fff5e1c3.gif

前兩篇聊到了一些技術,而這一篇我們則側重於思路,一起來聊一下階段3和階段4。

那麼,我們先看一下階段3的效果圖,慣例,前幾個階段的動畫我們用灰色 正常速度表示,當前階段則使用彩色慢速,如圖

1013170-2adfc8220d9b093c.gif

階段3

有的同學要說了,這個太簡單了,就是一平移嘛。

沒錯,就是平移。可能和我一樣,很多同學最早接觸的動畫就是平移、旋轉和縮放,可以算基本功了。

所以階段3,我們就不多聊了,方案有很多種,比如修改layer的position.y、transform.translation.y都可以(對此不熟悉的同學請戳官方文檔中的可動畫的屬性和動畫支持的key path),甚至可以用本系列第二篇提到的stroke方案。

階段3不是沒有價值,因為從階段3中我們可以得到一個重要結論,那就是:我們可以利用經驗來解決問題。

這句看上去像是廢話,不要急,我們接下來要看看,把分解問題和這個結論結合起來,會是什麼效果。

下面是階段4的效果圖,大家請看

1013170-a1020bc1e776c40f.gif

階段4

是不是感覺比前3個階段復雜,為什麼會有這種感覺呢?

一個重要的原因是,我們覺察到階段4是多個動畫組合而成的,不像前3個階段那樣是單個動畫。

像我一樣單核的同學估計要瘋了,恩,這兒在變,恩?那兒怎麼也在變?

所以我們最好還是把這組動畫分解一下,一個一個來處理。

但是怎麼分解呢,一時可能沒思路,那我們不如來描述一下這個動畫吧。

比如這樣:“一個圓被頭頂上的線砸扁了,線砸進圓裡,線變粗了。”

但仔細看看,砸進去的過程中,線在圓外的部分是細的,在圓內的部分是粗的,有點復雜,不如就以圓為界,分成一細一粗兩條線吧。

我們再描述一次:“一個圓被頭頂上的細線砸扁了,細線慢慢消失了,圓裡面慢慢出現了一條粗線。”

這個描述裡都有什麼?

圓漸漸扁了,圓外的細線漸漸消失了,圓內的粗線漸漸出現了。

漸漸,就是動畫的意思。

這樣我們就分解出了3個簡單的動畫,

為了更直觀,我們給圓、細線、粗線分別染上不同的顏色,請看下圖

05.gif

階段4 多彩版

思路是不是已經出來了,圓變扁,大家應該想到了基本功裡的縮放(transform.scale.y),線消失與線出現,有的同學可能想到了本系列第二篇提到的stroke方案(CAShapeLayer的strokeStart和strokeEnd)。

至此,我們已經通過描述問題,把動畫分解了,並且發現可以利用經驗實現分解後的動畫。

接下來就是找重要節點的值了。

我們發現,3者的交界是圓的頂點,看來這是一個重要的節點。

在本示例中,我們假設動畫結束時,圓的縮放系數scale為0.8,請看下圖

06.png

圖中紅點就是圓的頂點,由可知,動畫開始時,頂點y坐標就是center.y - r,結束時就是在這個基礎加上縮放的部分2r * (1 - scale),即center + 2r * (1 - scale)處。

再看細線,細線的長度可以從階段3中拿到,動畫開始時有長度(下圖中灰色線),動畫結束時,SS、SE重合,線就消失了(下圖中藍色圓的頂點),如圖

07.png

細線

再看粗線,我們假設結束時,粗線的底部位於圓未變形時的圓心處,動畫開始時SS、SE重合,線看不到(下圖中灰色圓的頂點),動畫結束時,SS、SE分別到了不同位置,線就出現了(下圖中藍色線),如圖

09.png

粗線

還不是很清楚的同學,可以在紙上畫一畫,畫著畫著就明白了。

至此,關鍵節點的值都找到了。

下面我們來看一個問題。

有的同學注意到了,這個圓的縮放和我們常用的不一樣,常用的是圓心不變,圓頂點和底點分別向圓心靠攏,形成橢圓的效果。而這個動畫中,是圓底點不動,頂點和圓心都向底點靠攏。

有經驗的同學可能要提到一個詞了,anchor point ,這個我先截一張官方文檔Core Animation Programming Guide中的示意圖,圖中用旋轉transform示意了anchor point和position。

112.png

不嚴謹的說,transform時,anchor point就是不動的那個點,其它點基於anchor point進行計算(具體大家還是要看一下Core Animation Programming Guide文檔,或它的翻譯版)。

具體到本例中,anchor point應該在圓的底點,這樣縮放時,就是底點不動,其他點基於底點計算了。

理解了anchor point,有的同學寫出了這一句。

self.arcToCircleLayer.anchorPoint = CGPointMake(0.5, 1);

這一句邏輯是對的,x等於0.5即anchor point在x軸上位於圓的中心,y等於1即anchor point在y軸上位於圓的底點,和我們前文中的說到的要求一致。

但執行時,卻會驚喜的發現,圓的位置發生了一次突變,如下圖

09.gif

這是怎麼了,想一想,圓的大小與位置可以認為是frame的體現,查看一下CALayer的文檔,在frame的Discussion中,有這麼一句

the frame rectangle is a computed property that is derived from the values in the bounds, anchorPoint and position properties.

也就是說frame是根據bounds、anchorPoint和position這3個屬性算出來的,我們沒有改變bounds和position,而單單改變了anchorPoint,frame自然也跟著變了。

怎麼解決呢,答案依然在frame的Discussion中,如下

When you assign a new value to this property, the layer changes its position and bounds properties to match the rectangle you specified.

文中的this property就是frame,這段文字說明,我們給frame指定新值,layer會自動調整position和bounds。

那就簡單了,我們設置anchor point後,再將圓的frame設置回之前的值,如下

CGRect frame = self.arcToCircleLayer.frame;
self.arcToCircleLayer.anchorPoint = CGPointMake(0.5, 1);
self.arcToCircleLayer.frame = frame;

篇幅關系,我就不貼大段代碼了,完整代碼大家可以查看GitHub上OneLoadingAnimation工程的OneLoadingAnimationStep4目錄。

為方便大家查看,我貼了一點代碼,說明一下代碼的結構,如下

// 第4階段
- (void)doStep4 {
    [self doStep4a];
    [self doStep4b];
    [self doStep4c];
}
// 4階段a:小圓變形
- (void)doStep4a {}

// 4階段b:逐漸消失的豎線
- (void)doStep4b {}

// 4階段c:逐漸出現的豎線
- (void)doStep4c {}

用1、2、3來表示某階段,用a、b、c來表示階段內某個動畫,這顯然不是良好的命名,但在這個示例中,這樣也許更清晰。

篇幅所限,我們在下一篇中再聊後續的階段,大家有興趣的話,可以分解一下後面的動畫,找一找感覺。

本文中提到解決問題的思路,相當一部分得益於V.Anton Spraul的《像程序員一樣思考》,ISBN號9787115383396,有興趣的同學可以看一下,寫的很好。

第三篇到這就告一段落了,非常感謝大家的觀看,我們下一篇再會。

階段4中我簡化的部分

大家仔細查看原動效的話,會發現圓的變化是不規則的。

原設計更符合直覺,比如大家把球放到地上,拿一個手指去按它,手指按的部分和球與地面接觸的部分,變形度肯定是不一樣的。

為了實現簡單,我將圓的變化處理成了規則的變化,即從圓漸漸變成了橢圓。

後續我會單獨開一篇和大家聊一下圓不規則變化的實現,敬請期待。

完整代碼

請參考GitHub上OneLoadingAnimation的OneLoadingAnimationStep3和OneLoadingAnimationStep4目錄。

本系列的傳送門

  • 一款Loading動畫的實現思路(一)

  • 一款Loading動畫的實現思路(二)

  • 一款Loading動畫的實現思路(三)

鳴謝及推薦

  • 原動效的設計者 moonjoin

  • 優秀的動效教程 Kitten's 時間膠囊

  • 喵神發起的objc中國的動畫部分,都是很優秀的譯文,衷心為翻譯的同學點贊。

相關鏈接

  • Core Animation Programming Guide

  • CALayer Class Reference

  • CAShapeLayer Class Reference

  • UIBezierPath Class Reference

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved