Skip to content

Instantly share code, notes, and snippets.

@hayabusabusa
Last active August 30, 2019 08:45
Show Gist options
  • Save hayabusabusa/e25daf5ca33b224d50ce2af54b307658 to your computer and use it in GitHub Desktop.
Save hayabusabusa/e25daf5ca33b224d50ce2af54b307658 to your computer and use it in GitHub Desktop.
Simple HUD
import UIKit
import PlaygroundSupport
// MARK: - Settings
let allSize: CGFloat = 200
let radius: CGFloat = 24.0
let smallRadius: CGFloat = 20.0
let nanoRadius: CGFloat = 16.0
// MARK: - View
let defaultView: UIView = .init(frame: CGRect(x: 0, y: 0, width: allSize, height: allSize))
defaultView.translatesAutoresizingMaskIntoConstraints = false
defaultView.backgroundColor = .white
// MARK: - Base shape
let baseShape: CAShapeLayer = .init()
baseShape.frame = defaultView.frame
baseShape.backgroundColor = UIColor.white.cgColor
defaultView.layer.addSublayer(baseShape)
// MARK: - Base circle path
let circlePath: UIBezierPath = .init(ovalIn: CGRect(x: radius, y: radius, width: allSize - radius * 2, height: allSize - radius * 2))
circlePath.apply(CGAffineTransform(translationX: allSize / 2, y: allSize / 2).inverted())
circlePath.apply(CGAffineTransform(rotationAngle: CGFloat.pi * 540 / 360))
circlePath.apply(CGAffineTransform(translationX: allSize / 2, y: allSize / 2))
// ######################### Normal HUD #############################
var circles: [CAShapeLayer] = [CAShapeLayer]()
for i in 0 ..< 5 {
let circle: CAShapeLayer = .init()
let circleRadius = radius - 4.0 * CGFloat(i)
circle.frame = CGRect(x: 0, y: 0, width: circleRadius * 2, height: circleRadius * 2)
circle.cornerRadius = circleRadius
circle.backgroundColor = UIColor.lightGray.withAlphaComponent(0.8).cgColor
circles.append(circle)
}
circles.enumerated().forEach { (offset, element) in
let positionAnimation: CAKeyframeAnimation = .init(keyPath: "position")
positionAnimation.path = circlePath.cgPath
positionAnimation.beginTime = CACurrentMediaTime() + 0.08 * Double(offset)
positionAnimation.duration = 1.6
positionAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
positionAnimation.repeatCount = .infinity
//baseShape.addSublayer(element)
//element.add(positionAnimation, forKey: "position")
}
// ######################### Normal HUD #############################
// ######################### Original HUD ###############################
let originalHudDuration: Double = 1.6
// MARK: - Path
let elipsePath: UIBezierPath = .init(ovalIn: CGRect(x: radius, y: radius * 3, width: allSize - radius * 2, height: allSize - radius * 6))
// 中心点をずらしてから回転させる
// https://dev.digitrick.us/notes/rotatingpathwithuibezierpath
elipsePath.apply(CGAffineTransform(translationX: allSize / 2, y: allSize / 2).inverted())
elipsePath.apply(CGAffineTransform(rotationAngle: CGFloat.pi * 60 / 360))
elipsePath.apply(CGAffineTransform(translationX: allSize / 2, y: allSize / 2))
let reverseElipsePath: UIBezierPath = .init(ovalIn: CGRect(x: radius, y: radius * 3, width: allSize - radius * 2, height: allSize - radius * 6))
reverseElipsePath.apply(CGAffineTransform(translationX: allSize / 2, y: allSize / 2).inverted())
reverseElipsePath.apply(CGAffineTransform(rotationAngle: CGFloat.pi * 300 / 360))
reverseElipsePath.apply(CGAffineTransform(translationX: allSize / 2, y: allSize / 2))
// MARK: - Shape
let rightCircle: CAShapeLayer = .init()
rightCircle.frame = CGRect(x: 0, y: 0, width: radius * 2, height: radius * 2)
rightCircle.cornerRadius = radius
rightCircle.backgroundColor = UIColor.red.cgColor
baseShape.addSublayer(rightCircle)
let leftCircle: CAShapeLayer = .init()
leftCircle.frame = CGRect(x: 0, y: 0, width: radius * 2, height: radius * 2)
leftCircle.cornerRadius = radius
leftCircle.backgroundColor = UIColor.blue.cgColor
baseShape.addSublayer(leftCircle)
// MARK: - Animation
let rightAnimation: CAKeyframeAnimation = .init(keyPath: "position")
rightAnimation.path = elipsePath.cgPath
rightAnimation.duration = originalHudDuration
rightAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
rightAnimation.repeatCount = .infinity
rightCircle.add(rightAnimation, forKey: "position")
let rightColorAnimation: CAKeyframeAnimation = .init(keyPath: "backgroundColor")
rightColorAnimation.values = [
UIColor.red.cgColor,
UIColor.green.cgColor,
UIColor.blue.cgColor
]
rightColorAnimation.keyTimes = [
0.0,
0.4,
0.95
]
rightColorAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
rightColorAnimation.duration = originalHudDuration
rightColorAnimation.repeatCount = .infinity
rightColorAnimation.autoreverses = true
rightCircle.add(rightColorAnimation, forKey: "backgroundColor")
let leftAnimation: CAKeyframeAnimation = .init(keyPath: "position")
leftAnimation.path = reverseElipsePath.cgPath
leftAnimation.duration = originalHudDuration
leftAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
leftAnimation.repeatCount = .infinity
leftCircle.add(leftAnimation, forKey: "position")
let leftColorAnimation: CAKeyframeAnimation = .init(keyPath: "backgroundColor")
leftColorAnimation.values = [
UIColor.blue.cgColor,
UIColor.yellow.cgColor,
UIColor.red.cgColor
]
leftColorAnimation.keyTimes = [
0.0,
0.4,
0.95
]
leftColorAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
leftColorAnimation.duration = originalHudDuration
leftColorAnimation.repeatCount = .infinity
leftColorAnimation.autoreverses = true
leftCircle.add(leftColorAnimation, forKey: "backgroundColor")
let scaleAnimation: CAKeyframeAnimation = .init(keyPath: "transform.scale")
scaleAnimation.values = [
1.0,
0.4,
1.0
]
scaleAnimation.keyTimes = [
0.0,
0.5,
0.8
]
scaleAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
scaleAnimation.duration = originalHudDuration
scaleAnimation.repeatCount = .infinity
rightCircle.add(scaleAnimation, forKey: "transform.scale")
leftCircle.add(scaleAnimation, forKey: "transform.scale")
// ######################### Original HUD ###############################
// MARK: - Preview
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = defaultView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment