Подтвердить что ты не робот

Создание круговой диаграммы с использованием Core Graphics

До сих пор у меня есть заполненный круг, и об этом. Я пытаюсь составить круговую диаграмму, которая представляет количество удовлетворенных и неудовлетворенных клиентов и представляет ее. Я чрезвычайно новичок в CG, и мне было интересно, кто-то может прокрутить достаточно кода, чтобы дать мне идею или направить меня.

Должен ли я иметь нижний круг, представляющий количество довольных клиентов, а затем добавить еще один круг поверх него, чтобы показать неудовлетворенных клиентов? Я подхожу к нему правильным образом?

Вот мой код.

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

Кроме того, теперь я начинаю видеть, что мне, возможно, придется покрыть мой круг дугой, основанной на общем недовольстве клиента. Как увеличить или уменьшить размер дуги покрытия на основе количества людей?

Любая помощь будет чрезвычайно оценена!

4b9b3361

Ответ 1

Вы захотите использовать CGContextAddArc() (CGContext.addArc() в Swift 3). Это позволит вам создать несколько сегментов для вашей круговой диаграммы, нарисовав дугу для каждого сегмента вашей круговой диаграммы.

Нечто подобное должно сработать:

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

Вы можете ввести данные своей круговой диаграммы в виде массива структур Segment, где каждый Segment представляет цвет и значение этого сегмента.

Значение может быть любым с плавающей точкой, и оно будет автоматически уменьшено до коэффициента, который будет использоваться на круговой диаграмме. Например, если вы хотите, чтобы ваша круговая диаграмма представляла число неудовлетворенных и удовлетворенных клиентов, вы можете просто передать значения непосредственно.

Пример использования:

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)

Выход:

enter image description here


Полный проект (с некоторыми дополнительными функциями): https://github.com/hamishknight/Pie-Chart-View

Ответ 2

Строка pieChartView.frame = CGRect (x: 0, y: 0, ширина: view.frame.size.width, высота: 400)

Возвращает ожидаемую ошибку компиляции замедления