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
Quick copy/paste Swift translation of this excellent Objective-C answer.
class ProgressView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
genericInit()
}
private func genericInit() {
self.opaque = false;
self.layer.contentsScale = UIScreen.mainScreen().scale
self.layer.setNeedsDisplay()
}
var progress : CGFloat = 0 {
didSet {
(self.layer as! ProgressLayer).progress = progress
}
}
override class func layerClass() -> AnyClass {
return ProgressLayer.self
}
func updateWith(progress : CGFloat) {
self.progress = progress
}
}
class ProgressLayer: CALayer {
@NSManaged var progress : CGFloat
override class func needsDisplayForKey(key: String!) -> Bool{
return key == "progress" || super.needsDisplayForKey(key);
}
override func actionForKey(event: String!) -> CAAction! {
if event == "progress" {
let animation = CABasicAnimation(keyPath: event)
animation.duration = 0.2
animation.fromValue = self.presentationLayer().valueForKey(event)
return animation
}
return super.actionForKey(event)
}
override func drawInContext(ctx: CGContext!) {
if progress != 0 {
let circleRect = CGRectInset(self.bounds, 1, 1)
let borderColor = UIColor.whiteColor().CGColor
let backgroundColor = UIColor.clearColor().CGColor
CGContextSetFillColorWithColor(ctx, backgroundColor)
CGContextSetStrokeColorWithColor(ctx, borderColor)
CGContextSetLineWidth(ctx, 2)
CGContextFillEllipseInRect(ctx, circleRect)
CGContextStrokeEllipseInRect(ctx, circleRect)
let radius = min(CGRectGetMidX(circleRect), CGRectGetMidY(circleRect))
let center = CGPointMake(radius, CGRectGetMidY(circleRect))
let startAngle = CGFloat(-(M_PI/2))
let endAngle = CGFloat(startAngle + 2 * CGFloat(M_PI * Double(progress)))
CGContextSetFillColorWithColor(ctx, borderColor)
CGContextMoveToPoint(ctx, center.x, center.y)
CGContextAddArc(ctx, center.x, center.y, radius, startAngle, endAngle, 0)
CGContextClosePath(ctx)
CGContextFillPath(ctx)
}
}
}