OneClock的翻頁時鐘效果是如何實現的

OneSwift - iOS Tips Based On Swiftgit

image

OneClock目前的三個錶盤中用戶最喜歡的是翻頁時鐘。翻頁效果是錶盤的核心,也是我花時間調試最久的細節。通過7次的產品迭代,終於調整到了一個合適的效果。github

image

實現這個動效的方法只需用到 CABasicAnimation中的以X軸旋轉便可。CABasicAnimation實際上還有不少參數,好比大小、透明度、背景顏色等,用這個方法作不少動畫都是能夠實現的。bash

製做翻頁時鐘的效果,實際上須要解決3個問題:app

1.只要時間刻度變更就提早翻頁;ide

2.真實演示出翻頁過程的遮蓋和層級效果;函數

3.正確顯示數字;動畫

實現過程

將翻頁的過程經過側面角度,解析成下圖中所示的樣子。翻頁的效果是從「上半頁」翻轉到「下半頁」,爲了讓過程顯得舒緩,我將翻頁的過程設定爲1.0秒。翻頁過程耗時1.0秒,所以在真實時間到達某一秒鐘時,須要判斷下一秒是否須要翻頁,若是翻頁,就馬上執行翻頁的過程。ui

image

翻頁過程不須要改變最底層的X層和Y層,它們繼續靜態顯示便可。以8點13分59秒爲例,當判斷下一秒爲8點14分時,將馬上生成A層、B層、C層,分別在下圖示意的位置。spa

image

A層、B層所顯示的數字爲當前的13,C層所顯示的數字爲下一秒的時間14,固然由於方向的問題C層翻轉以後其實是「下半層」。3d

image

一旦開始旋轉,A層、B層、C層覆蓋X層和Y層,此時的X層和Y層能夠提早賦予他們下一秒的時間14。

image

隨着不斷翻轉,0.5秒後,上半層露出下一個時間14,下半層仍然顯示的是當前時間13。

image

0.5秒到1.0秒之間,C層會逐步在下半部顯示,可以清晰地看到下一個數字爲14。翻頁1.0秒以後,時間恰好到達此刻的時間8點14分,A層、B層、C層的使命完成,馬上消失隱藏。X層和Y層提早1秒顯示了正確的時間,翻頁1.0秒後的時間恰好是咱們所見到的正確時間8點14分。

如此,翻頁過程結束。

image

​小時的翻頁和分鐘的翻頁其實是同樣的,只是小時翻頁的過程伴隨着分鐘同時翻頁,例如8點59分59秒的下一秒是9點00分,所以兩個翻頁將同時進行,而基本原理是同樣的。

相關代碼

在個人代碼實現中,「翻頁時鐘」和「檢測時間」兩個函數是分開獨立的,所以時鐘、分鐘甚至秒鐘均可以單獨執行翻頁。

最後,分享出OneClock的下載連接和翻頁函數的具體Swift代碼:

OneClock下載:https://itunes.apple.com/cn/app/id1257395357

翻頁函數:

func rotation(A:UIView,B:UIView,C:UIView){

    A.alpha = 1

    B.alpha = 1

    C.alpha = 1

    rotationFirst(view: B)

    //本文中提到的B,顯示13

    rotationSecond(view: C)

    //本文中提到的C,顯示14

    self.perform(#selector(self.initializeABC),with: nil, afterDelay: 0.9)

    //最後爲了過分順利,提早0.1秒讓A/B/C小時

    //initializeABC函數設置A/B/C隱藏

}
複製代碼
func rotationFirst(view:UIView){

    //舊值標籤,先出來

    let animation = CABasicAnimation(keyPath: "transform.rotation.x")

    animation.fromValue = (-10/360)*Double.pi

    animation.toValue = (-355/360)*Double.pi

    animation.duration = 1.0

    animation.repeatCount = 0

    animation.delegate = selfas? CAAnimationDelegate

    view.layer.add(animation, forKey: "rotationSecond")

    view.alpha = 1

}
複製代碼
func rotationSecond(view:UIView) {

    //新值標籤,後

    let animation = CABasicAnimation(keyPath: "transform.rotation.x")

    animation.fromValue = (355/360) * Double.pi

    animation.toValue = (10/360) * Double.pi

    animation.duration = 1.0

    animation.repeatCount = 0

    animation.delegate = self as? CAAnimationDelegate

    view.layer.add(animation, forKey: "rotationFirst")

    view.alpha = 1

}

複製代碼

GitHub:OneSwift - iOS Tips Based On Swift

微博:xDEHANG

相關文章
相關標籤/搜索