public class PieProgressView: UIView { public var progress:Float { get { return _progress } set { _progress = newValue self.updatePath() } } var borderWidth:Float = 2.0 { didSet { self.updatePath() } } override public var frame:CGRect { didSet { self.updatePath() } } static private let animationDuration = 0.6 public func setProgress(progress:Float, animated:Bool) { _progress = progress self.updatePath(animated) } private var _progress:Float = 0.0 init() { super.init(frame: CGRectZero) self.initialize() } override public init(frame: CGRect) { super.init(frame:frame) self.initialize() } required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.initialize() } public var fillColor:UIColor = UIColor.lightGrayColor() { didSet { self.shapeLayer.fillColor = self.fillColor.CGColor } } public var backgroundFillColor:UIColor = UIColor(red: 250.0/255.0, green: 250.0/255.0, blue: 250.0/255.0, alpha: 0.6) { didSet { self.backgroundShapeLayer.fillColor = self.backgroundFillColor.CGColor } } private let shapeLayer = CAShapeLayer() private let backgroundShapeLayer = CAShapeLayer() private func initialize() { self.backgroundColor = UIColor.clearColor() self.backgroundShapeLayer.fillColor = self.backgroundFillColor.CGColor self.layer.addSublayer(self.backgroundShapeLayer) self.shapeLayer.fillColor = self.fillColor.CGColor // self.shapeLayer.strokeColor = UIColor.redColor().CGColor self.layer.addSublayer(self.shapeLayer) self.updatePath() } private func updatePath(animated:Bool = false) { self.backgroundShapeLayer.path = UIBezierPath(ovalInRect: self.bounds).CGPath let center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)) let radius = center.y - CGFloat(2 * self.borderWidth) let angle = DegreesToRadians(Double((360.0 * _progress) + -90.0)) let points = [CGPointMake(center.x, CGFloat(self.borderWidth)), center, CGPointMake(center.x + radius * CGFloat(cosf(Float(angle))), center.y + radius * CGFloat(sinf(Float(angle))))] let path = UIBezierPath() path.moveToPoint(points[2]) path.addLineToPoint(points[1]) path.addLineToPoint(points[0]) path.addArcWithCenter(center, radius: radius, startAngle: CGFloat(DegreesToRadians(-90)), endAngle: CGFloat(angle), clockwise: true) if animated { let animation = CABasicAnimation(keyPath: "path") animation.duration = PieProgressView.animationDuration animation.fillMode = kCAFillModeForwards animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) animation.removedOnCompletion = true animation.fromValue = self.shapeLayer.path animation.toValue = path.CGPath self.shapeLayer.path = path.CGPath self.shapeLayer.addAnimation(animation, forKey: "path") } else { self.shapeLayer.path = path.CGPath } } }