You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.9 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. //
  2. // AnyValueProvider.swift
  3. // lottie-swift
  4. //
  5. // Created by Brandon Withrow on 1/30/19.
  6. //
  7. import CoreGraphics
  8. import Foundation
  9. // MARK: - AnyValueProvider
  10. /// `AnyValueProvider` is a protocol that return animation data for a property at a
  11. /// given time. Every frame an `AnimationView` queries all of its properties and asks
  12. /// if their ValueProvider has an update. If it does the AnimationView will read the
  13. /// property and update that portion of the animation.
  14. ///
  15. /// Value Providers can be used to dynamically set animation properties at run time.
  16. public protocol AnyValueProvider {
  17. /// The Type of the value provider
  18. var valueType: Any.Type { get }
  19. /// The type-erased storage for this Value Provider
  20. var typeErasedStorage: AnyValueProviderStorage { get }
  21. /// Asks the provider if it has an update for the given frame.
  22. func hasUpdate(frame: AnimationFrameTime) -> Bool
  23. }
  24. extension AnyValueProvider {
  25. /// Asks the provider to update the container with its value for the frame.
  26. public func value(frame: AnimationFrameTime) -> Any {
  27. typeErasedStorage.value(frame: frame)
  28. }
  29. }
  30. // MARK: - ValueProvider
  31. /// A base protocol for strongly-typed Value Providers
  32. protocol ValueProvider: AnyValueProvider {
  33. associatedtype Value: AnyInterpolatable
  34. /// The strongly-typed storage for this Value Provider
  35. var storage: ValueProviderStorage<Value> { get }
  36. }
  37. extension ValueProvider {
  38. public var typeErasedStorage: AnyValueProviderStorage {
  39. switch storage {
  40. case .closure(let typedClosure):
  41. return .closure(typedClosure)
  42. case .singleValue(let typedValue):
  43. return .singleValue(typedValue)
  44. case .keyframes(let keyframes):
  45. return .keyframes(
  46. keyframes.map { keyframe in
  47. keyframe.withValue(keyframe.value as Any)
  48. },
  49. interpolate: storage.value(frame:))
  50. }
  51. }
  52. }
  53. // MARK: - ValueProviderStorage
  54. /// The underlying storage of a `ValueProvider`
  55. public enum ValueProviderStorage<T: AnyInterpolatable> {
  56. /// The value provider stores a single value that is used on all frames
  57. case singleValue(T)
  58. /// The value provider stores a group of keyframes
  59. /// - The main-thread rendering engine interpolates values in these keyframes
  60. /// using `T`'s `Interpolatable` implementation.
  61. /// - The Core Animation rendering engine constructs a `CAKeyframeAnimation`
  62. /// using these keyframes. The Core Animation render server performs
  63. /// the interpolation, without calling `T`'s `Interpolatable` implementation.
  64. case keyframes([Keyframe<T>])
  65. /// The value provider stores a closure that is invoked on every frame
  66. /// - This is only supported by the main-thread rendering engine
  67. case closure((AnimationFrameTime) -> T)
  68. // MARK: Internal
  69. func value(frame: AnimationFrameTime) -> T {
  70. switch self {
  71. case .singleValue(let value):
  72. return value
  73. case .closure(let closure):
  74. return closure(frame)
  75. case .keyframes(let keyframes):
  76. return KeyframeInterpolator(keyframes: ContiguousArray(keyframes)).storage.value(frame: frame)
  77. }
  78. }
  79. }
  80. // MARK: - AnyValueProviderStorage
  81. /// A type-erased representation of `ValueProviderStorage`
  82. public enum AnyValueProviderStorage {
  83. /// The value provider stores a single value that is used on all frames
  84. case singleValue(Any)
  85. /// The value provider stores a group of keyframes
  86. /// - Since we can't interpolate a type-erased `KeyframeGroup`,
  87. /// the interpolation has to be performed in the `interpolate` closure.
  88. case keyframes([Keyframe<Any>], interpolate: (AnimationFrameTime) -> Any)
  89. /// The value provider stores a closure that is invoked on every frame
  90. case closure((AnimationFrameTime) -> Any)
  91. // MARK: Internal
  92. func value(frame: AnimationFrameTime) -> Any {
  93. switch self {
  94. case .singleValue(let value):
  95. return value
  96. case .closure(let closure):
  97. return closure(frame)
  98. case .keyframes(_, let valueForFrame):
  99. return valueForFrame(frame)
  100. }
  101. }
  102. }