ActivityIndicatorAnimationBallClipRotateMultiple.swift 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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 ActivityIndicatorAnimationBallClipRotateMultiple: ActivityIndicatorAnimating {
  7. // MARK: Properties
  8. fileprivate let duration: CFTimeInterval = 0.7
  9. // MARK: ActivityIndicatorAnimating
  10. public func configureAnimation(in layer: CALayer, size: CGSize, color: UIColor) {
  11. let bigCircleSize: CGFloat = size.width
  12. let smallCircleSize: CGFloat = size.width / 2
  13. let longDuration: CFTimeInterval = 1
  14. let timingFunction: TimingFunctionType = .easeInOut
  15. let circleLayer1 = makeCircleLayerOf(shape: .ringTwoHalfHorizontal,
  16. duration: longDuration,
  17. timingFunction: timingFunction,
  18. layerSize: layer.frame.size,
  19. size: bigCircleSize,
  20. color: color, reverse: false)
  21. let circleLayer2 = makeCircleLayerOf(shape: .ringTwoHalfVertical,
  22. duration: longDuration,
  23. timingFunction: timingFunction,
  24. layerSize: layer.frame.size,
  25. size: smallCircleSize,
  26. color: color, reverse: true)
  27. layer.addSublayer(circleLayer1)
  28. layer.addSublayer(circleLayer2)
  29. }
  30. }
  31. // MARK: - Setup
  32. private extension ActivityIndicatorAnimationBallClipRotateMultiple {
  33. func makeAnimation(duration: CFTimeInterval, timingFunction: TimingFunctionType, reverse: Bool) -> CAAnimation {
  34. // Scale animation
  35. let scaleAnimation = CAKeyframeAnimation(keyPath: .scale)
  36. scaleAnimation.keyTimes = [0, 0.5, 1]
  37. scaleAnimation.timingFunctionsType = [timingFunction, timingFunction]
  38. scaleAnimation.values = [1, 0.6, 1]
  39. scaleAnimation.duration = duration
  40. // Rotate animation
  41. let rotateAnimation = CAKeyframeAnimation(keyPath: .rotationZ)
  42. rotateAnimation.keyTimes = scaleAnimation.keyTimes
  43. rotateAnimation.timingFunctionsType = [timingFunction, timingFunction]
  44. if !reverse {
  45. rotateAnimation.values = [0, CGFloat.pi, 2 * CGFloat.pi]
  46. } else {
  47. rotateAnimation.values = [0, -CGFloat.pi, -2 * CGFloat.pi]
  48. }
  49. rotateAnimation.duration = duration
  50. // Animation
  51. let animation = CAAnimationGroup()
  52. animation.animations = [scaleAnimation, rotateAnimation]
  53. animation.duration = duration
  54. animation.repeatCount = .infinity
  55. animation.isRemovedOnCompletion = false
  56. return animation
  57. }
  58. // swiftlint:disable:next function_parameter_count
  59. func makeCircleLayerOf(shape: ActivityIndicatorShape,
  60. duration: CFTimeInterval,
  61. timingFunction: TimingFunctionType,
  62. layerSize: CGSize,
  63. size: CGFloat,
  64. color: UIColor,
  65. reverse: Bool) -> CALayer {
  66. let circleLayer = shape.makeLayer(size: CGSize(width: size, height: size), color: color)
  67. let frame = CGRect(x: (layerSize.width - size) / 2,
  68. y: (layerSize.height - size) / 2,
  69. width: size,
  70. height: size)
  71. let animation = makeAnimation(duration: duration, timingFunction: timingFunction, reverse: reverse)
  72. circleLayer.frame = frame
  73. circleLayer.add(animation, forKey: "animation")
  74. return circleLayer
  75. }
  76. }