寫一個酷炫的iOS進度條動畫

發表於2017-02-01

最近需要寫個進度條動畫,之前在github上看到JSDownloadView時就想也自己實現一個,於是就去網上找了一下好看的進度條動畫素材準備實現以下。

先把原圖放一下:

111249505-a143ba1e530ce372

121249505-04140c363a414341

第一個進度條出處是這裡,第二個進度條是正好在CocoaChina的一篇文章中看到儲存下來的沒有找到原出處;

一共做了兩款進度條,但其實實現的都不是很完美。

這兩個動畫我完全用的是CoreAimation實現,由於對POP不是很熟悉,不知道如何用POP實現類似CAKeyFrameAnimation的關鍵幀動畫,所以沒有采用POP。

具體的實現思路和上面所說的JSDownloadView是類似的,簡而言之就是分解組合動畫。

1.利用Mac自帶的預覽可以檢視GIF中的一幀幀影像,可以具體觀察GIF是如何一步步變化的,方便你拆解組合動畫

2.取出幾個關鍵幀方便我們回想動畫實現

131249505-c9a69d8e72b56b22

1.png

141249505-9c17b39dcd88811e

2.png

151249505-aee247e374caaa95

3.png

161249505-4fdbb0d7af261df2

4.png

3.首先我們需要把初始狀態給畫出來,先建立兩個CAShapeLayer,此處還需要用UIBezierPath畫出layer的path,如果不是很熟悉的可以看一下這個文章,寫動畫的過程中需要繪製大量的貝塞爾曲線

我的想法是circleLayer經過動畫後由圓圈變為橫線進度條,箭頭所用的arrowLayer變為筆,這樣動畫都在這兩個layer上面進行,思路比較清晰

4.初始狀態繪製好之後就需要開始動畫,由上面的分解可知:

  • 圓圈->曲線->橫線;箭頭->鉛筆。這些都是形變只需設定layer.path屬性即可
  • 由於圓圈變為曲線這段動畫需要畫貝塞爾曲線比較多,而且我想到的實現方法只有利用CAKeyFrameAnimation的values設定path來實現,所以沒有新增,顯得這段過渡比較突兀(若有好的想法歡迎聯絡我)
  • 可以看到箭頭有一個先向上位移->然後再移動到起點的動畫;
    使用CAAnimationGroup封裝動畫讓箭頭的向上跳動和變化為鉛筆的動畫同時進行
  • 而圓圈則是變為曲線有一個波浪狀的動畫

關於此處用到的UIBezierPath還是提一下把(不熟悉的可以看一下我上面提到的那篇文章):
呼叫下面這個方法繪製二次貝塞爾曲線,看下圖就明白這個方法怎麼使用了
-(void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;

171249505-09c8770c3f9d1fed

貝塞爾.png
  • 此處動畫結束後應該是箭頭變為了鉛筆 並且移動到了頂端,曲線也停止波動此時需要連貫動畫,繼續讓鉛筆移動到進度條起點,並開始進度動畫,鉛筆移動到起點的動畫也就是繪一段移動曲線,只要能算出起點終點就沒什麼問題,此處不再贅述。
  • 連貫動畫使用的CoreAnimation的delegate,監聽前一段動畫結束後繼續下一段動畫。其實也可以使用CoreAnimation中的beginTime屬性,只要你能將動畫開始結束時間算的很清楚使用這個方法也很不錯。若你使用POP實現動畫的話,POP有動畫完成的completionBlock則更方便
  • 此時前期準備動畫已經完成,鉛筆移動到起點可以開始設定進度移動鉛筆。移動鉛筆我使用的方法是設定arrowLayer(鉛筆)的transform,但是這樣做的缺點就是你在之後算一些貝塞爾曲線的路徑時,要注意layer的transform屬性
  • 改變進度條顏色我的做法是建立一個新的layer然後通過不斷設定其path來實現進度條的變化

5.到此處大致的思路和主要的實現方法已經都說完了,收尾和開始的準備動畫都是一樣的型別,按照其中的動畫組合實現即可,動畫其中有很多小細節,小動畫文章裡都沒有提到

最終效果:

181249505-668075c6cfff5adf

progress1

191249505-4678501349b7c2a2

progress2failed.gif

201249505-9cb120df3f757642

progress2success.gif

總結一下:

主要使用到的類:CABasicAnimation,CAKeyFrameAnimation,CAAnimationGroup,UIBezierPath
將動畫通過Group,beginTime和delegate的方式按順序組合播放即可完成一系列複雜動畫

關於animation的keypath不清楚的可以看這裡

相對來說第二個素材的動畫更容易實現而且效果更平滑,有時間再寫一下把

程式碼放在github,喜歡的朋友歡迎star

寫在最後:看了程式碼的和實際效果的朋友若有什麼改進意見 歡迎探討,有幾個效果實現起來實在差,特別第二個動畫下載速度快慢時指示器角度的變化完全沒有實現思路。

相關文章