前面幾課所學的「動畫效果」,一則是利用 Animation 物件,根據時間曲線用內插法計算兩個視圖中間的過程,一則是利用「定時器」Timer 物件提供時間,按時觸發視圖本身狀態的變化。歸納起來,動畫的關鍵要素離不開「時間」,可以說「時間」驅動了動畫的效果。

本課將介紹SwiftUI新的時間軸視圖 TimelineView,是第3種製作動畫效果的方式,從名稱就可看出,這個視圖物件也跟時間有關。

TimelineView 是一種視圖容器(View Container),與 VStack, HStack, List, NavigationView...等排版功能的容器類似,可用來容納別的視圖,在第2單元第4課(2-4c)提過,容器內的視圖可稱為子視圖。

如果說,排版功能的容器是用來控制子視圖的空間排列,那麼,時間軸視圖就是控制子視圖的「時間排程」。我們先用一個簡單的範例程式,來看看時間軸視圖能做什麼:

// 4-4a TimelineView (時間軸視圖)
// Created by Heman, 2022/04/07
import PlaygroundSupport
import SwiftUI

struct 週期性排程: View {
    var body: some View {
        TimelineView(.periodic(from: Date(), by: 1.0)) { 時間參數 in
            Text("\\(時間參數.date)")
                .font(.title2)
                .padding()
        }
    }
}

struct 連續時間排程: View {
    var body: some View {
        TimelineView(.animation) { 時間參數 in
            let 本地曆法 = Calendar.current
            let 秒數 = 本地曆法.component(.second, from: 時間參數.date)
            let 奈秒 = 本地曆法.component(.nanosecond, from: 時間參數.date)
            Text("\\(時間參數.date)\\n\\(秒數):\\(奈秒)")
                .font(.title2)
                .onAppear {
                    print(時間參數.date)
                    print(時間參數.cadence)
                }
        }
    }
}

struct 時間軸視圖: View {
    var body: some View {
        週期性排程()
        連續時間排程()
    }
}

PlaygroundPage.current.setLiveView(時間軸視圖())

時間軸的語法和其他視圖類似,需要一個參數並尾隨一個匿名函式,參數需提供「時間排程(Schedule)」,時間軸視圖會在時間排程的每一時刻,將「時間參數」帶入匿名函式中。

範例第一部分設定為「週期性排程」(periodic),從現在時刻Date()開始,每1.0秒鐘更新一次容器內的子視圖:

TimelineView(.periodic(from: Date(), by: 1.0)) { 時間參數 in
    Text("\\(時間參數.date)")
        .font(.title2)
        .padding()
}

參數時間排程(Schedule)目前有以下5種預設屬性或方法,本節範例使用前兩個最常用的排程,以初步熟悉時間軸視圖的物件特性:

  1. periodic(from: 起始時間, by: 週期間隔) — 週期性排程
  2. animation — 動畫排程或連續排程,物件屬性
  3. animation(minimumInterval: 最短間隔, paused: 可否暫停)
  4. everyMinute — 分鐘週期排程,物件屬性
  5. explicit(時間序列) — 明確排程或有限排程
Powered by Fruition