難度:??
最終效果:

平時在逛一些設計相關網(wǎng)站時總想把一些效果實現(xiàn)一下,這次挑了 Google Material Design的練一下手。
我們可以把動畫簡單地分解為 路徑填充 + 旋轉(zhuǎn):

仔細考慮一番,可以發(fā)現(xiàn)用改變 CAShapeLayer 的 strokeStart 和 strokeEnd 實現(xiàn)。整個填充看起來像 strokeEnd跑的快, strokeStart開始跑得慢,但在 strokeEnd跑到終點后突然加速追趕。
但似乎時間函數(shù)沒那么好控制,因為它顯得不那么規(guī)律。在這種情況下,我們可以使用關鍵幀動畫實現(xiàn)這種不規(guī)則的時間函數(shù)控制。我簡單地把它分為了三個時間點: 0,0.5,1.0。
時間點 0:strokeEnd出發(fā)了一點點,但 strokeEnd還沒動。
時間點 0.5:strokeEnd已經(jīng)跑到了終點,strokeEnd才跑了一點距離。
時間點 1.0:strokeEnd在終點等著,strokeStart加速趕到了終點。
經(jīng)過此番分析后,動畫相關的代碼大致如下:
let strokeDuration:Double = 2
func strokeStartAnimation() -> CAKeyframeAnimation {
let animation = CAKeyframeAnimation(keyPath: "strokeStart")
animation.keyTimes = [0, 0.5, 1]
animation.values = [0, 0.3, 1]
animation.duration = strokeDuration
animation.fillMode = kCAFillModeForwards
animation.repeatCount = Float.infinity
return animation
}
func strokeEndAnimation() -> CAKeyframeAnimation {
let animation = CAKeyframeAnimation(keyPath: "strokeEnd")
animation.keyTimes = [0, 0.5, 1]
animation.values = [0.05, 1, 1]
animation.duration = strokeDuration
animation.fillMode = kCAFillModeForwards
animation.repeatCount = Float.infinity
return animation
}
把這兩個動畫加到了圖層上,就能看到?jīng)]有旋轉(zhuǎn)情況下的效果。再完善一下,添加一個比路徑填充稍微慢一點的旋轉(zhuǎn)動畫,就能達到文初那種似乎不規(guī)則的 loading效果。
不足之處:在路徑動畫一次結(jié)束后切換下一次時感覺沒那么過渡自然,那是因為使用路徑填充實現(xiàn)。如果使用改變路徑長度實現(xiàn)會更好一點(CSS中就可以通過 stroke dash array/offset修改填充長度實現(xiàn)),但在 iOS中,CAShapeLayer的 lineDashPattern 不是 animatable的,導致不能按照 CSS的思路去實現(xiàn)。
其實可以自定義繪制,不過稍顯麻煩,如果你追求 pixel perfect,那就那么做吧。
-EOF-