Animated CAShapeLayer Pie

后端 未结 4 2017
遥遥无期
遥遥无期 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 16:58

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

提交回复
热议问题