enum Style {
case donut
case circle
}
private let kMaxProgress: Float = 1.0
private var style = Style.donut
private var trackTintColor: UIColor = UIColor.gray
private var progressTintColor: UIColor = UIColor.orange
private var lineWidth: Float = 0.0
private var progress: Float = 0.0
private var animation: Bool = false
func drawDonutChart(progress: Float, lineWidth: Float = 5.0, trackColor: UIColor = UIColor.rgb(233, 239, 241), progressColor: UIColor = UIColor.rgb(5, 200, 123)) {
self.style = .donut
self.progress = progress
self.lineWidth = lineWidth
self.trackTintColor = trackColor
self.progressTintColor = progressColor
setNeedsDisplay()
}
func drawDonutChartWithAnimation(progress: Float, lineWidth: Float = 5.0, progressColor: UIColor = UIColor.rgb(5, 200, 123)) {
self.animation = true
self.layer.sublayers = nil
let layer = CAShapeLayer()
layer.frame = self.bounds
layer.strokeColor = progressColor.cgColor
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = CGFloat(lineWidth)
layer.path = bezierCgPath(progress: progress)
layer.strokeEnd = 1
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = 0.5
animation.fromValue = 0.0
animation.toValue = 1.0
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
layer.add(animation, forKey: nil)
self.layer.addSublayer(layer)
}
func drawPieChart(color: UIColor = UIColor.rgb(233, 239, 241)) {
self.lineWidth = 0
self.lineWidth = 0
self.style = .circle
self.trackTintColor = color
setNeedsDisplay()
}
private func drawDonutProgress(progress: Float, center: CGPoint, radius: CGFloat, context: CGContext) {
UIGraphicsPushContext(context)
context.beginPath()
let startAngle = -Float.pi / 2.0
let endAngle = startAngle + (progress * 2.0 * Float.pi)
context.addArc(center: center, radius: radius, startAngle: CGFloat(startAngle), endAngle: CGFloat(endAngle), clockwise: false)
context.strokePath()
UIGraphicsPopContext()
}
private func drawPieProgress(progress: Float, center: CGPoint, radius: CGFloat, context: CGContext) {
UIGraphicsPushContext(context)
context.beginPath()
let startAngle = -Float.pi / 2.0
let endAngle = startAngle + (progress * 2.0 * Float.pi)
context.move(to: center)
context.addArc(center: center, radius: radius, startAngle: CGFloat(startAngle), endAngle: CGFloat(endAngle), clockwise: false)
context.closePath()
context.fillPath()
UIGraphicsPopContext()
}
private func bezierCgPath(progress: Float) -> CGPath {
let bezierPath = UIBezierPath()
bezierPath.addArc(withCenter: CGPoint(x: layer.frame.size.width / 2.0, y: layer.frame.size.height / 2.0),
radius: layer.frame.size.width / 2.0,
startAngle: CGFloat(-Float.pi / 2.0),
endAngle: CGFloat(-Float.pi / 2.0 + (progress * 2.0 * Float.pi)),
clockwise: true)
return bezierPath.cgPath
}
override func draw(_ rect: CGRect) {
if animation {
return
}
var middlePoint = CGPoint()
middlePoint.x = self.bounds.origin.x + self.bounds.size.width / 2.0
middlePoint.y = self.bounds.origin.y + self.bounds.size.height / 2.0
var radius = min(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0)
radius -= (CGFloat(lineWidth) / 2.0)
let context = UIGraphicsGetCurrentContext()
context?.saveGState()
context?.setLineWidth(CGFloat(lineWidth))
if let context = context {
switch style {
case .donut:
trackTintColor.setStroke()
drawDonutProgress(progress: kMaxProgress, center: middlePoint, radius: radius, context: context)
progressTintColor.setStroke()
drawDonutProgress(progress: progress, center: middlePoint, radius: radius, context: context)
case .circle:
trackTintColor.setFill()
drawPieProgress(progress: kMaxProgress, center: middlePoint, radius: radius, context: context)
}
}
context?.restoreGState()
}
}
댓글 없음:
댓글 쓰기