ListViewAnimation
protocol
Interpolatable
1
static func interpolator() -> (Interpolatable, Interpolatable, CGFloat) -> (Interpolatable)
class
ListViewAnimation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let from: Interpolatable
let to: Interpolatable
let duration: Double
let startTime: Double
private let curve: (CGFloat) -> CGFloat
private let interpolator: (Interpolatable, Interpolatable, CGFloat) -> Interpolatable
private let update: (CGFloat, Interpolatable) -> Void
private let completed: (Bool) -> Void
public init<T: Interpolatable>(from: T, to: T, duration: Double, curve: @escaping (CGFloat) -> CGFloat, beginAt: Double, update: @escaping (CGFloat, T) -> Void, completed: @escaping (Bool) -> Void = { _ in }) {
self.from = from
self.to = to
self.duration = duration
self.curve = curve
self.startTime = beginAt
self.interpolator = T.interpolator()
self.update = { progress, value in
update(progress, value as! T)
}
self.completed = completed
}
completeAt
1
2
3
4
5
6
7
8
public func completeAt(_ timestamp: Double) -> Bool {
if timestamp >= self.startTime + self.duration {
self.completed(true)
return true
} else {
return false
}
}
valueAt
1
2
3
4
5
6
7
8
9
private func valueAt(_ t: CGFloat) -> Interpolatable {
if t <= 0.0 {
return self.from
} else if t >= 1.0 {
return self.to
} else {
return self.interpolator(self.from, self.to, t)
}
}
applyAt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public func applyAt(_ timestamp: Double) {
var t = CGFloat((timestamp - self.startTime) / self.duration)
let ct: CGFloat
if t <= 0.0 + CGFloat.ulpOfOne {
t = 0.0
ct = 0.0
} else if t >= 1.0 - CGFloat.ulpOfOne {
t = 1.0
ct = 1.0
} else {
ct = self.curve(t)
}
self.update(ct, self.valueAt(ct))
}