It would be nice to be able to monitor when a LOTAnimationView's current frame changes, to sync other events with the change. It seems this may be possible using a callback block on a known element in the animation but that is a bit overkill. I apologize if I've missed this and it already exists.
Essentially something like:
let animationView = LOTAnimationView(...)
animationView.onFrameChange = { (currentFrame, currentProgress, currentTime) in
print("The animation is now on \(currentFrame)")
}
Or via some kind of delegate:
let animationView = LOTAnimationView(...)
animationView.stateChangeDelegate = self
/// LOTAnimationViewStateDelegate
func animationView(_ animationView: LOTAnimationView, didChangeCurrentFrame currentFrame: Int) {
}
func didStartPlayingAnimationView(_ animationView: LOTAnimationView) {
}
func didStopPlayingAnimationView(_ animationView: LOTAnimationView) {
}
There doesn't appear to be a non-trivial way of accomplishing this.
After further investigation it appears this is pretty trivial using a CADisplayLink. It would still be nice to have the functionality built-in without needing to hijack the run loop but this works fine. Example below:
class AnimationProgressObserver {
typealias ProgressChangeBlock = (_ progress: CGFloat)->()
private weak var animationView: LOTAnimationView?
private var onChange: ProgressChangeBlock
private var lastAnimationProgress: CGFloat = -1
init(animationView: LOTAnimationView, onChange: @escaping ProgressChangeBlock) {
self.animationView = animationView
self.onChange = onChange
let displayLink: CADisplayLink = CADisplayLink(target: self, selector: #selector(displayLinkTick))
displayLink.add(to: RunLoop.current, forMode: .commonModes)
}
@objc private func displayLinkTick() {
guard let currentProgress = animationView?.animationProgress else {
return
}
if lastAnimationProgress != currentProgress {
lastAnimationProgress = currentProgress
onChange(currentProgress)
}
}
}
Usage:
let animationView = LOTAnimationView(name: "...")
let progressObserver = AnimationProgressObserver(animationView: animationView, onChange: { (progress: CGFloat) in
print("The animation is now at \(progress) progress")
})
Now available in Lottie 3.0 use realtimeAimationFrame
Lottie has been completely rewritten in Swift as of 3.0 (https://github.com/airbnb/lottie-ios/pull/777)
I am closing all issues prior to this release to reduce the noise. If you continue to run into this issues or any issue with Lottie 3.0 please open a new ticket
For continued support of Lottie Objective-c please point to this branch: https://github.com/airbnb/lottie-ios/tree/lottie/objectiveC
Most helpful comment
After further investigation it appears this is pretty trivial using a CADisplayLink. It would still be nice to have the functionality built-in without needing to hijack the run loop but this works fine. Example below:
Usage: