Я собрал класс, который будет немного имитировать c a ValueAnimator
из android и позволит вам при необходимости указать собственную кривую анимации (по умолчанию это просто линейный)
Простое использование
let valueAnimator = ValueAnimator(duration: 2) { value in
animationView.animationProgress = value
}
valueAnimator.start()
Расширенное использование
let valueAnimator = ValueAnimator(from: 0, to: 100, duration: 60, animationCurveFunction: { time, duration in
return atan(time)*2/Double.pi
}, valueUpdater: { value in
animationView.animationProgress = value
})
valueAnimator.start()
Вы также можете отменить его в любой момент, используя:
valueAnimator.cancel()
Значение Класс аниматора в Swift 5
// swiftlint:disable:next private_over_fileprivate
fileprivate var defaultFunction: (TimeInterval, TimeInterval) -> (Double) = { time, duration in
return time / duration
}
class ValueAnimator {
let from: Double
let to: Double
var duration: TimeInterval = 0
var startTime: Date!
var displayLink: CADisplayLink?
var animationCurveFunction: (TimeInterval, TimeInterval) -> (Double)
var valueUpdater: (Double) -> Void
init (from: Double = 0, to: Double = 1, duration: TimeInterval, animationCurveFunction: @escaping (TimeInterval, TimeInterval) -> (Double) = defaultFunction, valueUpdater: @escaping (Double) -> Void) {
self.from = from
self.to = to
self.duration = duration
self.animationCurveFunction = animationCurveFunction
self.valueUpdater = valueUpdater
}
func start() {
displayLink = CADisplayLink(target: self, selector: #selector(update))
displayLink?.add(to: .current, forMode: .default)
}
@objc
private func update() {
if startTime == nil {
startTime = Date()
valueUpdater(from + (to - from) * animationCurveFunction(0, duration))
return
}
var timeElapsed = Date().timeIntervalSince(startTime)
var stop = false
if timeElapsed > duration {
timeElapsed = duration
stop = true
}
valueUpdater(from + (to - from) * animationCurveFunction(timeElapsed, duration))
if stop {
cancel()
}
}
func cancel() {
self.displayLink?.remove(from: .current, forMode: .default)
self.displayLink = nil
}
}
Возможно, вы могли бы улучшить это, чтобы быть более обобщенным c, но это служит моей цели.