Last active
April 23, 2019 18:26
-
-
Save paulofierro/ecfbebde1659d523044fbfefb6b2b9b8 to your computer and use it in GitHub Desktop.
Arc progress
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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