不知道大家有沒有發現,iPhone 主畫面左右滑動切換頁面,或是抖音用上下滑動切換頁面的操作,與上一節圖片輪播非常類似,只是自動輪播改成手動輪播。手動輪播要如何做呢?
如果仔細觀察iPhone主畫面或抖音的手勢操作,會發現一個關鍵細節:
因此,手動輪播其實有兩段行程,第一段是用「拖曳」手勢,控制左右滑動或上下滑動;當拖曳手勢結束時,若滑動速率不夠,則回到原畫面,若速率夠快,則啟動第二段行程,自動繼續滑到下一頁停止。概念如下圖:
第一段手動行程比較簡單,用「拖曳」手勢來控制畫布的左右滑動,當手勢結束時,測量水平滑動的速度,若速率小於300(點/秒),則回到起始點,若大於300(點/秒)則停在原處不動(接續第二段自動行程)。
第一段程式如下:
// 4-9c 手動輪播(拖曳手勢) -- 第一段
// Created by Heman, 2022/06/24
import PlaygroundSupport
import SwiftUI
struct 畫布: View {
@State var 拖曳位移: CGSize = .zero
@State var 拖曳開始 = Date()
var 拖曳: some Gesture {
DragGesture()
.onChanged { 拖曳參數 in
if 拖曳位移 == .zero { 拖曳開始 = 拖曳參數.time }
拖曳位移 = 拖曳參數.translation
}
.onEnded { 拖曳參數 in
let 時間差 = 拖曳參數.time.timeIntervalSince(拖曳開始)
let 速度 = 拖曳參數.translation.width / 時間差
if abs(速度) < 300 {
拖曳位移 = .zero
}
// print(時間差, 拖曳參數.translation)
// print(速度)
}
}
var body: some View {
Canvas { 圖層, 尺寸 in
let 寬 = 尺寸.width
let 高 = 尺寸.height
let 半徑 = min(寬/2, 高/2)
let 中心 = CGPoint(x: 寬/2, y: 高/2)
圖層.translateBy(x: 拖曳位移.width, y: 0)
var 畫筆 = Path()
for i in [-1.0, 0.0, 1.0] {
let 圓心 = CGPoint(x: 中心.x + 寬*i, y: 中心.y)
let 起點 = CGPoint(x: 中心.x + 寬*(i+0.5), y: 中心.y)
畫筆.move(to: 起點)
畫筆.addArc(
center: 圓心,
radius: 半徑,
startAngle: .zero,
endAngle: .degrees(360),
clockwise: false)
}
圖層.stroke(畫筆, with: .color(.cyan), lineWidth: 20.0)
}
.border(.red)
.gesture(拖曳)
Circle()
.frame(height: 200)
.border(.blue)
.foregroundColor(.blue)
.offset(拖曳位移)
.gesture(拖曳)
}
}
PlaygroundPage.current.setLiveView(畫布())
先看看執行的過程:
上方較大的空心圓是用畫布(Canvas)所繪,下方較小的實心圓則是Circle()視圖,兩者都顯示視框邊界(.border()),也同樣套用「拖曳」手勢(.gesture()),可以藉此觀察到幾個特點: