Open getaaron opened 8 years ago
This helped me so much. Thank you @getaaron !
@getaaron's code was terrific!
I found myself wanting to control whether-or-not the animation blocks were repeatable, so I made a small modification by adding an allowsRepetition
property. If allowsRepetition = false
, then the behavior matches @getaaron's implementation.
However, if allowsRepetition = true
, then the animation can be replayed. (Of course, this could lead to some goofy behavior, so you'll probably want some animation blocks to "reset" the animation, etc.) While it requires a bit of extra debugging / playtesting, I found that it's really nice for people to be able to replay the animation by scrolling back in the tutorial, rather than only seeing it once!
public class TriggeredBlockAnimation: Animatable {
public typealias TriggeredBlock = () -> Void
private var blocks = [CGFloat: TriggeredBlock]()
private let allowsRepetition: Bool
init(allowsRepetition: Bool) {
self.allowsRepetition = allowsRepetition
}
private var suppressAnimations: Bool = false
public func animate(_ time: CGFloat) {
guard let block = blocks[time], !self.suppressAnimations else { return }
block()
if !allowsRepetition {
blocks[time] = nil // ensures block is only run once ever
}
}
public subscript(time: CGFloat) -> TriggeredBlock? {
get { return blocks[time] }
set { blocks[time] = newValue }
}
}
Instead of animations that are always proportional to the scroll view's
contentOffset
, we sometimes want a normalUIView
animation to be triggered at a certain point.Here's a basic implementation:
This could be used like so:
You could also use this approach for triggering other one-time events, like playing a sound, or triggering an analytics event, at a specific offset.