前面幾課所學的「動畫效果」,一則是利用 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種預設屬性或方法,本節範例使用前兩個最常用的排程,以初步熟悉時間軸視圖的物件特性: