ActivityIndicatorAnimationPacman.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. //
  2. // Created by Tom Baranes on 23/08/16.
  3. // Copyright (c) 2016 IBAnimatable. All rights reserved.
  4. //
  5. import UIKit
  6. public class ActivityIndicatorAnimationPacman: ActivityIndicatorAnimating {
  7. // MARK: Properties
  8. fileprivate let duration: CFTimeInterval = 0.5
  9. fileprivate let circleDuration: CFTimeInterval = 1
  10. fileprivate var size: CGSize = .zero
  11. fileprivate let timingFunction: TimingFunctionType = .default
  12. // MARK: ActivityIndicatorAnimating
  13. public func configureAnimation(in layer: CALayer, size: CGSize, color: UIColor) {
  14. self.size = size
  15. animateCircle(in: layer, color: color)
  16. animatePacman(in: layer, color: color)
  17. }
  18. }
  19. // MARK: - Pacman
  20. private extension ActivityIndicatorAnimationPacman {
  21. func animatePacman(in layer: CALayer, color: UIColor) {
  22. let pacmanSize = 2 * size.width / 3
  23. let pacman = ActivityIndicatorShape.pacman.makeLayer(size: CGSize(width: pacmanSize, height: pacmanSize), color: color)
  24. let animation = pacmanAnimation
  25. let frame = CGRect(
  26. x: (layer.bounds.size.width - size.width) / 2,
  27. y: (layer.bounds.size.height - size.height) / 2 + size.height / 2 - pacmanSize / 2,
  28. width: pacmanSize,
  29. height: pacmanSize
  30. )
  31. pacman.frame = frame
  32. pacman.add(animation, forKey: "animation")
  33. layer.addSublayer(pacman)
  34. }
  35. var pacmanAnimation: CAAnimationGroup {
  36. let animation = CAAnimationGroup()
  37. animation.animations = [strokeStartAnimation, strokeEndAnimation]
  38. animation.duration = duration
  39. animation.repeatCount = .infinity
  40. animation.isRemovedOnCompletion = false
  41. return animation
  42. }
  43. var strokeStartAnimation: CAKeyframeAnimation {
  44. let strokeStartAnimation = CAKeyframeAnimation(keyPath: .strokeStart)
  45. strokeStartAnimation.keyTimes = [0, 0.5, 1]
  46. strokeStartAnimation.timingFunctionsType = [timingFunction, timingFunction]
  47. strokeStartAnimation.values = [0.125, 0, 0.125]
  48. strokeStartAnimation.duration = duration
  49. return strokeStartAnimation
  50. }
  51. var strokeEndAnimation: CAKeyframeAnimation {
  52. let strokeEndAnimation = CAKeyframeAnimation(keyPath: .strokeEnd)
  53. strokeEndAnimation.keyTimes = [0, 0.5, 1]
  54. strokeEndAnimation.timingFunctionsType = [timingFunction, timingFunction]
  55. strokeEndAnimation.values = [0.875, 1, 0.875]
  56. strokeEndAnimation.duration = duration
  57. return strokeEndAnimation
  58. }
  59. }
  60. // MARK: - Circle
  61. private extension ActivityIndicatorAnimationPacman {
  62. func animateCircle(in layer: CALayer, color: UIColor) {
  63. let circleSize = size.width / 5
  64. let circle = ActivityIndicatorShape.circle.makeLayer(size: CGSize(width: circleSize, height: circleSize), color: color)
  65. let animation = circleAnimation
  66. let frame = CGRect(
  67. x: (layer.bounds.size.width - size.width) / 2 + size.width - circleSize,
  68. y: (layer.bounds.size.height - size.height) / 2 + size.height / 2 - circleSize
  69. / 2,
  70. width: circleSize,
  71. height: circleSize
  72. )
  73. circle.frame = frame
  74. circle.add(animation, forKey: "animation")
  75. layer.addSublayer(circle)
  76. }
  77. var circleAnimation: CAAnimationGroup {
  78. let animation = CAAnimationGroup()
  79. animation.animations = [translateAnimation, opacityAnimation]
  80. animation.timingFunctionType = .linear
  81. animation.duration = circleDuration
  82. animation.repeatCount = .infinity
  83. animation.isRemovedOnCompletion = false
  84. return animation
  85. }
  86. var translateAnimation: CABasicAnimation {
  87. let translateAnimation = CABasicAnimation(keyPath: .translationX)
  88. translateAnimation.fromValue = 0
  89. translateAnimation.toValue = -size.width / 2
  90. translateAnimation.duration = circleDuration
  91. return translateAnimation
  92. }
  93. var opacityAnimation: CABasicAnimation {
  94. let opacityAnimation = CABasicAnimation(keyPath: .opacity)
  95. opacityAnimation.fromValue = 1
  96. opacityAnimation.toValue = 0.7
  97. opacityAnimation.duration = circleDuration
  98. return opacityAnimation
  99. }
  100. }