📜  quartzcore 框架 pi 图表 - Swift 代码示例

📅  最后修改于: 2022-03-11 15:01:01.732000             🧑  作者: Mango

代码示例1
//Swift Pie chart
//https://stackoverflow.com/a/34250475/13171606
//https://stackoverflow.com/questions/36708737/how-to-create-the-pie-chart-and-fill-percentage-in-swift

import Foundation
import UIKit

@IBDesignable class PieChart: UIView {
    var dataPoints: Dictionary = ["Alpha":1,"Beta":2,"Charlie":3,"Delta":4,"Echo":2.5,"Foxtrot":1.4] {
        didSet { setNeedsDisplay() }
    }
    @IBInspectable var lineWidth: CGFloat = 1.0 {
        didSet { setNeedsDisplay()
        }
    }
    @IBInspectable var lineColor: UIColor = uicolor_normal {
        didSet { setNeedsDisplay() }
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder:aDecoder)!
        self.contentMode = .Redraw
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.clearColor()
        self.contentMode = .Redraw
    }

    override func drawRect(rect: CGRect) {


        // set font for labels
        let fieldColor: UIColor = UIColor.darkGrayColor()
        let fieldFont = uifont_piechartkey
        var fieldAttributes: NSDictionary = [
            NSForegroundColorAttributeName: fieldColor,
            NSFontAttributeName: fieldFont!
        ]

        // get the graphics context and prepare an inset box for the pie
        let ctx = UIGraphicsGetCurrentContext()
        let margin: CGFloat = lineWidth
        let box0 = CGRectInset(self.bounds, margin, margin)
        let keyHeight = CGFloat( ceil( Double(dataPoints.count) / 3.0) * 24 ) + 16
        let side : CGFloat = min(box0.width, box0.height-keyHeight)
        let box = CGRectMake((self.bounds.width-side)/2, (self.bounds.height-side-keyHeight)/2,side,side)
        let radius : CGFloat = min(box.width, box.height)/2.0


        // converts percentages to radians for drawing the segment
        func percent_to_rad(p: Double) -> CGFloat {
            let rad = CGFloat(p * 0.02 * M_PI)
            return rad
        }

        // draws a segment
        func draw_arc(start: CGFloat, end: CGFloat, color: CGColor) {
            CGContextBeginPath(ctx)
            CGContextMoveToPoint(ctx, box.midX, box.midY)
            CGContextSetFillColorWithColor(ctx, color)
            CGContextAddArc(ctx,box.midX,box.midY,radius-lineWidth/2,start,end,0)
            CGContextClosePath(ctx)
            CGContextFillPath(ctx)
        }
        // draws a key item
        func draw_key(keyName: String, keyValue: Double, color: CGColor, keyX: CGFloat, keyY: CGFloat) {
            CGContextBeginPath(ctx)
            CGContextMoveToPoint(ctx, keyX, keyY)
            CGContextSetFillColorWithColor(ctx, color)
            CGContextAddArc(ctx,keyX,keyY,8,0,CGFloat(2 * M_PI),0)
            CGContextClosePath(ctx)
            CGContextFillPath(ctx)
            keyName.drawInRect(CGRectMake(keyX + 12,keyY-8,self.bounds.width/3,16),withAttributes: fieldAttributes as? [String : AnyObject])
        }


        let total =  Double(dataPoints.values.reduce(0, combine: +)) // the total of all values
        // convert dictionary to sorted touples
        let dataPointsArray = dictionary_to_sorted_array(dataPoints)

        // now sort the dictionary into an Array
        var start = -CGFloat(M_PI_2) // start at 0 degrees, not 90
        var end: CGFloat
        var i = 0

        // draw all segments
        for dataPoint in dataPointsArray {
            end = percent_to_rad(Double( (dataPoint.value)/total) * 100 )+start
            draw_arc(start,end:end,color: uicolors_chart[i%uicolors_chart.count].CGColor)
            start = end
            i++
        }
        // the key
        var keyX = self.bounds.minX + 8
        var keyY = self.bounds.height - keyHeight + 32
            i = 0
        for dataPoint in dataPointsArray {
            draw_key(dataPoint.key, keyValue: dataPoint.value, color: uicolors_chart[i%uicolors_chart.count].CGColor, keyX: keyX, keyY: keyY)
            if((i+1)%3 == 0) {
                keyX = self.bounds.minX + 8
                keyY += 24
            } else {
                keyX += self.bounds.width / 3
            }
            i++
        }



    }
}

//This will create a pie chart, that looks something like this:

//[The finished chart[https://i.stack.imgur.com/K4hda.png]

//The other bits of code you'll need are the colours array:
        //"please follow the link for colors array" https://stackoverflow.com/a/34250475/13171606

//And the code to convert the dictionary to an array:

func dictionary_to_sorted_array(dict:Dictionary) ->Array<(key:String,value:Double)> {
    var tuples: Array<(key:String,value:Double)> = Array()
    let sortedKeys = (dict as NSDictionary).keysSortedByValueUsingSelector("compare:")
    for key in sortedKeys {
        tuples.append((key:key as! String,value:dict[key as! String]!))
    }
    return tuples
}