AnimationChainable.swift 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. //
  2. // Created by jason akakpo on 01/01/2017.
  3. // Copyright © 2017 IBAnimatable. All rights reserved.
  4. //
  5. import Foundation
  6. import UIKit
  7. typealias AnimationTuple = (type: AnimationType, configuration: AnimationConfiguration)
  8. struct AnimationConfiguration {
  9. let damping: CGFloat
  10. let velocity: CGFloat
  11. let duration: TimeInterval
  12. let delay: TimeInterval
  13. let force: CGFloat
  14. let timingFunction: TimingFunctionType
  15. }
  16. extension AnimationConfiguration {
  17. /// Options for spring animation.
  18. var options: UIView.AnimationOptions {
  19. if let curveOption = timingFunction.viewAnimationCurveOption {
  20. return [
  21. .allowUserInteraction,
  22. curveOption,
  23. .overrideInheritedCurve,
  24. .overrideInheritedOptions,
  25. .overrideInheritedDuration]
  26. }
  27. return [.allowUserInteraction]
  28. }
  29. }
  30. public class AnimationPromise<T: UIView> where T: Animatable {
  31. private var view: T
  32. private var animationList = [AnimationTuple]()
  33. private var delayForNextAnimation = 0.0
  34. private var completion: AnimatableCompletion?
  35. init(view: T) {
  36. self.view = view
  37. }
  38. func animationCompleted() {
  39. animationList.removeFirst()
  40. if let currentAnimation = animationList.first {
  41. view.doAnimation(currentAnimation.type, configuration: currentAnimation.configuration, promise: self)
  42. } else {
  43. completion?()
  44. }
  45. }
  46. public func completion(_ completion: AnimatableCompletion?) {
  47. self.completion = completion
  48. }
  49. @discardableResult
  50. public func then(_ animation: AnimationType,
  51. duration: TimeInterval? = nil,
  52. damping: CGFloat? = nil,
  53. velocity: CGFloat? = nil,
  54. force: CGFloat? = nil,
  55. timingFunction: TimingFunctionType? = nil) -> AnimationPromise {
  56. let configuration = AnimationConfiguration(damping: damping ?? view.damping,
  57. velocity: velocity ?? view.velocity,
  58. duration: duration ?? view.duration,
  59. delay: delayForNextAnimation,
  60. force: force ?? view.force,
  61. timingFunction: timingFunction ?? view.timingFunction)
  62. let animTuple = AnimationTuple(type: animation, configuration: configuration)
  63. animationList.append(animTuple)
  64. if animationList.count == 1 { // If it's the only animation, launch it immediately
  65. view.doAnimation(animation, configuration: animTuple.configuration, promise: self)
  66. }
  67. delayForNextAnimation = 0
  68. return self
  69. }
  70. @discardableResult
  71. public func delay(_ delay: TimeInterval) -> AnimationPromise {
  72. delayForNextAnimation = delay
  73. return self
  74. }
  75. }