ActivityIndicatorAnimationCubeTransition.swift 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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 ActivityIndicatorAnimationCubeTransition: ActivityIndicatorAnimating {
  7. // MARK: Properties
  8. fileprivate let duration: CFTimeInterval = 1.6
  9. fileprivate let timingFunction: TimingFunctionType = .easeInOut
  10. fileprivate let keyTimes: [NSNumber] = [0, 0.25, 0.5, 0.75, 1]
  11. fileprivate var deltaX: CGFloat = 0
  12. fileprivate var deltaY: CGFloat = 0
  13. // MARK: ActivityIndicatorAnimating
  14. public func configureAnimation(in layer: CALayer, size: CGSize, color: UIColor) {
  15. let squareSize = size.width / 5
  16. let x = (layer.bounds.size.width - size.width) / 2
  17. let y = (layer.bounds.size.height - size.height) / 2
  18. let beginTime = layer.currentMediaTime
  19. let beginTimes: [CFTimeInterval] = [0, -0.8]
  20. deltaX = size.width - squareSize
  21. deltaY = size.height - squareSize
  22. for i in 0 ..< 2 {
  23. let square = ActivityIndicatorShape.rectangle.makeLayer(size: CGSize(width: squareSize, height: squareSize), color: color)
  24. let frame = CGRect(x: x, y: y, width: squareSize, height: squareSize)
  25. animation.beginTime = beginTime + beginTimes[i]
  26. square.frame = frame
  27. square.add(animation, forKey: "animation")
  28. layer.addSublayer(square)
  29. }
  30. }
  31. }
  32. // MARK: - Setup
  33. private extension ActivityIndicatorAnimationCubeTransition {
  34. var animation: CAAnimationGroup {
  35. let animation = CAAnimationGroup()
  36. animation.animations = [scaleAnimation, translateAnimation, rotateAnimation]
  37. animation.duration = duration
  38. animation.repeatCount = .infinity
  39. animation.isRemovedOnCompletion = false
  40. return animation
  41. }
  42. var rotateAnimation: CAKeyframeAnimation {
  43. let rotateAnimation = CAKeyframeAnimation(keyPath: .rotationZ)
  44. rotateAnimation.keyTimes = keyTimes
  45. rotateAnimation.timingFunctionsType = [timingFunction, timingFunction, timingFunction, timingFunction]
  46. rotateAnimation.values = [0, -CGFloat.pi / 2, -CGFloat.pi, -1.5 * CGFloat.pi, -2 * CGFloat.pi]
  47. rotateAnimation.duration = duration
  48. return rotateAnimation
  49. }
  50. var scaleAnimation: CAKeyframeAnimation {
  51. let scaleAnimation = CAKeyframeAnimation(keyPath: .scale)
  52. scaleAnimation.keyTimes = keyTimes
  53. scaleAnimation.timingFunctionsType = [timingFunction, timingFunction, timingFunction, timingFunction]
  54. scaleAnimation.values = [1, 0.5, 1, 0.5, 1]
  55. scaleAnimation.duration = duration
  56. return scaleAnimation
  57. }
  58. var translateAnimation: CAKeyframeAnimation {
  59. let translateAnimation = CAKeyframeAnimation(keyPath: .translation)
  60. translateAnimation.keyTimes = keyTimes
  61. translateAnimation.timingFunctionsType = [timingFunction, timingFunction, timingFunction, timingFunction]
  62. translateAnimation.values = [
  63. NSValue(cgSize: CGSize(width: 0, height: 0)),
  64. NSValue(cgSize: CGSize(width: deltaX, height: 0)),
  65. NSValue(cgSize: CGSize(width: deltaX, height: deltaY)),
  66. NSValue(cgSize: CGSize(width: 0, height: deltaY)),
  67. NSValue(cgSize: CGSize(width: 0, height: 0))
  68. ]
  69. translateAnimation.duration = duration
  70. return translateAnimation
  71. }
  72. }