I am trying to create a simple and animated pie chart using CAShapeLayer. I want it to animate from 0 to a provided percentage.
To create the shape laye
In Swift 3
class ProgressView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
genericInit()
}
private func genericInit() {
self.isOpaque = false;
self.layer.contentsScale = UIScreen.main.scale
self.layer.setNeedsDisplay()
}
var progress : CGFloat = 0 {
didSet {
(self.layer as! ProgressLayer).progress = progress
}
}
override class var layerClass: AnyClass {
return ProgressLayer.self
}
func updateWith(progress : CGFloat) {
self.progress = progress
}
}
class ProgressLayer: CALayer {
@NSManaged var progress : CGFloat
override class func needsDisplay(forKey key: String) -> Bool{
return key == "progress" || super.needsDisplay(forKey: key);
}
override func action(forKey event: String) -> CAAction? {
if event == "progress" {
let animation = CABasicAnimation(keyPath: event)
animation.duration = 0.2
animation.fromValue = self.presentation()?.value(forKey: event) ?? 0
return animation
}
return super.action(forKey: event)
}
override func draw(in ctx: CGContext) {
if progress != 0 {
let circleRect = self.bounds.insetBy(dx: 1, dy: 1)
let borderColor = UIColor.white.cgColor
let backgroundColor = UIColor.red.cgColor
ctx.setFillColor(backgroundColor)
ctx.setStrokeColor(borderColor)
ctx.setLineWidth(2)
ctx.fillEllipse(in: circleRect)
ctx.strokeEllipse(in: circleRect)
let radius = min(circleRect.midX, circleRect.midY)
let center = CGPoint(x: radius, y: circleRect.midY)
let startAngle = CGFloat(-(Double.pi/2))
let endAngle = CGFloat(startAngle + 2 * CGFloat(Double.pi * Double(progress)))
ctx.setFillColor(borderColor)
ctx.move(to: CGPoint(x:center.x , y: center.y))
ctx.addArc(center: CGPoint(x:center.x, y: center.y), radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
ctx.closePath()
ctx.fillPath()
}
}
}