Animated CAShapeLayer Pie

后端 未结 4 2034
遥遥无期
遥遥无期 2020-12-13 16:16

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

4条回答
  •  醉酒成梦
    2020-12-13 17:08

    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()
            }
        }
    }
    

提交回复
热议问题