使用Core Graphics制作饼图 [英] Making a pie chart using Core Graphics

查看:130
本文介绍了使用Core Graphics制作饼图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到目前为止,我已经填满了一个圆圈,就是这样。我正在尝试制作一个饼图,代表满意和不满意客户的数量并展示它。我对CG非常陌生,并且想知道有人可以提出足够的代码给我一个想法或指导我。



我是否应该在底部圆圈表示满意客户的数量,然后在其上添加另一个圆圈以显示不满意的客户?我是以正确的方式接近它吗?



这是我到目前为止的代码。

 覆盖func drawRect(rect:CGRect){

//获取当前上下文
let context = UIGraphicsGetCurrentContext()

//设置颜色
CGContextSetStrokeColorWithColor(上下文,UIColor(红色:0.2,绿色:0.4,蓝色:1,alpha:1.0).CGColor)

let rectangle = CGRectMake((frame.size.width / 3) - 50,frame.size.height / 2 + 40,220,220)
CGContextAddEllipseInRect(context,rectangle)

CGContextSetFillColorWithColor(context,UIColor(红色:0.2,绿色:0.4,蓝色:1,alpha:1.0).CGColor)
CGContextFillPath(context)
CGContextStrokePath(context)

}

编辑



此外,现在我开始看到我可能需要根据不满意客户的总和来覆盖我的圆圈。如何根据人数增加或减少覆盖弧的大小?



任何帮助都将非常感激!

解决方案

您需要使用






完整项目(带有一些额外功能): https://github.com/hamishknight/Pie-Chart-View


So far I have a filled in circle and that's about it. I'm trying to make a pie chart that represents the number of satisfied and unsatisfied customers and present it. I'm extremely new to CG and was wondering someone can crank out enough code to give me an idea or to guide me.

Should I have the bottom circle represent the number of satisfied customers and then add another circle on top of it to show the unsatisfied customers? Am I approaching it in the right way?

Here is my code so far.

override func drawRect(rect: CGRect) {

    // Get current context
    let context = UIGraphicsGetCurrentContext()

    // Set color
    CGContextSetStrokeColorWithColor(context,UIColor(red: 0.2, green: 0.4, blue: 1, alpha: 1.0).CGColor)

    let rectangle = CGRectMake((frame.size.width / 3) - 50, frame.size.height / 2 + 40,220,220)
    CGContextAddEllipseInRect(context,rectangle)

    CGContextSetFillColorWithColor(context, UIColor(red: 0.2, green: 0.4, blue: 1, alpha: 1.0).CGColor)
    CGContextFillPath(context)
    CGContextStrokePath(context)

}

EDIT

Also, now i'm starting to see that I might need to cover my circle with an arc based off of the total of dissatisfied customer. How can I increase or decrease the size of the covering arc based on the number of people?

Any help would be tremendously appreciated!

解决方案

You'll want to use the CGContextAddArc() function (CGContext.addArc() in Swift 3). This will let you create multiple segments for your pie chart by drawing an arc for each segment of your pie chart.

Something like this should do the trick:

import UIKit

struct Segment {

    // the color of a given segment
    var color: UIColor

    // the value of a given segment – will be used to automatically calculate a ratio
    var value: CGFloat
}

class PieChartView: UIView {

    /// An array of structs representing the segments of the pie chart
    var segments = [Segment]() {
        didSet {
            setNeedsDisplay() // re-draw view when the values get set
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        isOpaque = false // when overriding drawRect, you must specify this to maintain transparency.
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {

        // get current context
        let ctx = UIGraphicsGetCurrentContext()

        // radius is the half the frame's width or height (whichever is smallest)
        let radius = min(frame.size.width, frame.size.height) * 0.5

        // center of the view
        let viewCenter = CGPoint(x: bounds.size.width * 0.5, y: bounds.size.height * 0.5)

        // enumerate the total value of the segments by using reduce to sum them
        let valueCount = segments.reduce(0, {$0 + $1.value})

        // the starting angle is -90 degrees (top of the circle, as the context is flipped). By default, 0 is the right hand side of the circle, with the positive angle being in an anti-clockwise direction (same as a unit circle in maths).
        var startAngle = -CGFloat.pi * 0.5

        for segment in segments { // loop through the values array

            // set fill color to the segment color
            ctx?.setFillColor(segment.color.cgColor)

            // update the end angle of the segment
            let endAngle = startAngle + 2 * .pi * (segment.value / valueCount)

            // move to the center of the pie chart
            ctx?.move(to: viewCenter)

            // add arc from the center for each segment (anticlockwise is specified for the arc, but as the view flips the context, it will produce a clockwise arc)
            ctx?.addArc(center: viewCenter, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: false)

            // fill segment
            ctx?.fillPath()

            // update starting angle of the next segment to the ending angle of this segment
            startAngle = endAngle
        }
    }
}

You can input your pie chart data as an array of Segment structs, where each Segment represents the color and value of that segment.

The value can be any float, and will automatically be reduced down to a ratio to be used in the pie chart. So for example, if you want your pie chart to represent the number of unsatisfied vs. number of satisfied customers, you can just pass the values directly in.

Example of usage:

let pieChartView = PieChartView()
pieChartView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 400)
pieChartView.segments = [
    Segment(color: .red, value: 57),
    Segment(color: .blue, value: 30),
    Segment(color: .green, value: 25),
    Segment(color: .yellow, value: 40)
]
view.addSubview(pieChartView)

Output:


Full project (with some extra functionality): https://github.com/hamishknight/Pie-Chart-View

这篇关于使用Core Graphics制作饼图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆