Skip to content

Instantly share code, notes, and snippets.

@paulofierro
Last active April 23, 2019 18:26
Show Gist options
  • Save paulofierro/ecfbebde1659d523044fbfefb6b2b9b8 to your computer and use it in GitHub Desktop.
Save paulofierro/ecfbebde1659d523044fbfefb6b2b9b8 to your computer and use it in GitHub Desktop.
Arc progress
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
class ArcProgressViewController : UIViewController {
private lazy var backgroundLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.frame = CGRect(x: 25, y: 25, width: 325, height: 325)
layer.fillColor = UIColor.lightGray.cgColor
return layer
}()
private let progressLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.fillColor = UIColor.darkGray.cgColor
return layer
}()
private var currentProgress: CGFloat = 0 {
didSet {
drawProgress(currentProgress)
}
}
override func loadView() {
let view = UIView()
view.backgroundColor = .white
self.view = view
drawBackgroundCircle()
createDisplayLink()
}
/// Create the dispaly link to update the screen
private func createDisplayLink() {
let displaylink = CADisplayLink(target: self, selector: #selector(handleDisplayUpdate))
displaylink.add(to: .current, forMode: .default)
}
/// Update the screen
@objc private func handleDisplayUpdate(displayLink: CADisplayLink) {
currentProgress += 0.005
// Wrap around once we get to 1 for an endless loop
if currentProgress > 1 {
currentProgress = 0
}
}
/// Draws the circle behind the progress layer
private func drawBackgroundCircle() {
drawPath(in: backgroundLayer, progress: 1)
view.layer.addSublayer(backgroundLayer)
}
/// Updates the progressLayer with the current progress
private func drawProgress(_ progress: CGFloat) {
guard progress >= 0, progress <= 1 else {
return
}
if progressLayer.frame == .zero {
let diff: CGFloat = 10
var frame = backgroundLayer.frame
frame.origin.x += diff
frame.origin.y += diff
frame.size.width -= diff * 2
frame.size.height -= diff * 2
progressLayer.frame = frame
progressLayer.transform = CATransform3DMakeRotation(CGFloat.pi/180 * 270, 0, 0, 1.0);
view.layer.addSublayer(progressLayer)
}
drawPath(in: progressLayer, progress: progress)
}
/// Draws an arc of progress in the layer that's passed in
private func drawPath(in layer: CAShapeLayer, progress: CGFloat) {
let frame = layer.frame
let startPoint = CGPoint(x: frame.width, y: frame.height / 2.0)
let centerPoint = CGPoint(x: frame.width / 2.0, y: frame.height / 2.0)
let startAngle = CGFloat(0)
let endAngle = progress * CGFloat.pi * 2
let path = UIBezierPath()
path.move(to: centerPoint)
path.addLine(to: startPoint)
path.addArc(withCenter: centerPoint,
radius: frame.width / 2.0,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
path.addLine(to: centerPoint)
path.close()
layer.path = path.cgPath
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = ArcProgressViewController()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment