iOS图表:在PieChart中显示百分比的实际值?

时间:2017-08-14 08:21:29

标签: ios ios-charts

我目前正在使用Charts - by Daniel Gindi,在他的演示之后,我已经实现了像这样的PieChart:

enter image description here

使用以下代码实现:

func createPieChart(dataPoints: [String: Double])
{
    for index in 0..<sortedDates.count
    {
        let year = sortedDates[index]

        guard let costs = dataPoints[year] else {
            return
        }

        let dataEntry = PieChartDataEntry(value: costs, label: year)

        dataEntries.append(dataEntry)
    }

    chartDataSet = PieChartDataSet(values: dataEntries, label: "")

    chartData = PieChartData(dataSet: chartDataSet)

    chartDataSet.sliceSpace = 2.0

    chartDataSet.yValuePosition = PieChartDataSet.ValuePosition.outsideSlice

    ...

    pieChartView.usePercentValuesEnabled = true
    pieChartView.drawSlicesUnderHoleEnabled = false
    pieChartView.holeRadiusPercent = 0.40
    pieChartView.transparentCircleRadiusPercent = 0.43
    pieChartView.drawHoleEnabled = true
    pieChartView.rotationAngle = 0.0
    pieChartView.rotationEnabled = true
    pieChartView.highlightPerTapEnabled = false

    let pieChartLegend = pieChartView.legend
    pieChartLegend.horizontalAlignment = Legend.HorizontalAlignment.right
    pieChartLegend.verticalAlignment = Legend.VerticalAlignment.top
    pieChartLegend.orientation = Legend.Orientation.vertical
    pieChartLegend.drawInside = false
    pieChartLegend.yOffset = 10.0

    pieChartView.legend.enabled = true

    pieChartView.data = chartData
}

我想要实现的是在饼图切片内显示实际的costs值,但也包括切片外的百分比。百分比使用chartDataSet.yValuePosition = PieChartDataSet.ValuePosition.outsideSlice显示。

检查代码时,我注意到在PieChartRenderer中有函数open override func drawValues(context: CGContext)并且在其中,代码计算valueText中每个饼图片的百分比:

let valueText = formatter.stringForValue(
                    value,
                    entry: e,
                    dataSetIndex: i,
                    viewPortHandler: viewPortHandler)

然后使用if检查,它绘制切片内部或外部的百分比,在我的情况下是在外面:

else if drawYOutside
{
    ChartUtils.drawText(
                        context: context,
                        text: valueText,
                        point: CGPoint(x: 0, y: labelPoint.y + lineHeight / 2.0),
                        align: align,
                        attributes: [NSFontAttributeName: valueFont, NSForegroundColorAttributeName: valueTextColor]
                        )
}

但是,我无法找到实际包含传递到costs的{​​{1}}值的方法。

我被告知继承饼图并覆盖我找到的方法,但我不确定如何做到这一点。

例如,PieChartDataEntry(value: costs, label: year)中每个索引的costs值对于标签dataPoints和标100.02017的双倍值50.0。我想在关联的饼图片中包含这两个值。

这个图书馆有经验的人可以帮助我吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

创建一个继承自PieChartRenderer的类,并覆盖父类的drawValues,如下所示:

public class CustomClass: PieChartRenderer
{
    override public func drawValues(context: CGContext)
    {
        // In this body, copy ALL code from parent class drawValues function

        ...
        let decimalFormatter = NumberFormatter()
        decimalFormatter.minimumFractionDigits = 2
        decimalFormatter.maximumFractionDigits = 2
        decimalFormatter.positivePrefix = "$"

        ...

        for i in 0 ..< dataSets.count
        {
            ...

            for j in 0 ..< dataSet.entryCount
            {
                ...

                guard let e = dataSet.entryForIndex(j) else { continue }
                let pe = e as? PieChartDataEntry

                // e.y = the actual value in the costs array, not the percentage
                let twoDecimalValue = NSDecimalNumber(value: e.y)
                let totalCost = decimalFormatter.string(from: twoDecimalValue)

                ...

                if drawXInside || drawYInside
                {
                    ...

                    if drawXInside && drawYInside
                    {
                        ...
                    }
                    else if drawXInside
                    {
                        if j < data.entryCount && pe?.label != nil
                        {
                            ChartUtils.drawText(
                                context: context,
                                text: pe!.label!,
                                point: CGPoint(x: x,
                                               y: y),
                                align: .center,
                                attributes: [NSFontAttributeName: yearValueFont,
                                             NSForegroundColorAttributeName: yearTextColor ?? percentageTextColor]
                            )

                            ChartUtils.drawText(
                                context: context,
                                text: totalCost!,
                                point: CGPoint(x: x,
                                               y: y + lineHeight),
                                align: .center,
                                attributes: [NSFontAttributeName: yearCostsValueFont,
                                             NSForegroundColorAttributeName: yearCostsTextColor]
                            )
                        }
                    }
                }
            }
        }
    }
}

else if drawXInside内,第一个现有 drawText函数会绘制label值,在我的情况下,。添加另一个drawText函数并传入totalCost值,该值表示数组`cost中的实际值。

然后在createPieChart函数中:

func createPieChart(dataPoints: [String: Double])
{
    ...

    pieChartView.data = chartData

    let customClass = CustomClass(chart: pieChartView, 
                                  animator: pieChartView.chartAnimator,
                                  viewPortHandler: pieChartView.viewPortHandler)
    pieChartView.renderer = customRenderer   
}

结果:

enter image description here

答案 1 :(得分:-1)

您需要将yValuePosition属性更改为insideSlice

pieChartDataSet.yValuePosition = PieChartDataSet.ValuePosition.insideSlice

默认情况下,它在内部,但您指定为外侧,以便在图表外显示。

修改:

根据评论请查看以下代码,该代码显示PieChart中的值不是百分比

func setPieChartData(lables: [String]!, values:[Double]!) {

        var valuesArray: [PieChartDataEntry] = []
        var colors: [UIColor] = []
        let valNSArray = values as NSArray

        valNSArray.enumerateObjects({ object, index, stop in
            //your code
            colors.append(self.getRandomColor())


            valuesArray.append(PieChartDataEntry(value: object as! Double, label: lables[index]))

        })

        let pieChartDataSet = PieChartDataSet(values: valuesArray, label: "Pie Data Chart")
        pieChartDataSet.colors = colors

        let piechartData = PieChartData(dataSets:[pieChartDataSet])
        pieChartDataSet.yValuePosition = PieChartDataSet.ValuePosition.insideSlice
        self.data = piechartData



}

enter image description here

希望这会有所帮助。