Charts(swift) 饼状图、柱状图使用

2,688 阅读5分钟

最近项目当中需要用到图标,然后在上查了下,找到了这个,感觉应该比较好用。github地址

饼状图

饼图

1.倒入Charts,然后实历化饼状图的类PieChartView

import Charts
class WorkManagerHeaderView: UICollectionReusableView {
    
    let lableTitle:UILabel = {
        return UILabel.label(font: fontVaue)
    }()
    //饼状图的数据
    var months = ["1-9", "10-19", "20-29", "30-39","40-49"]
    var unitsSold = [30.0, 100.0, 108.0, 60.0, 50.0]
    //饼状图
    lazy var pieChartView: PieChartView = {
        let pieChartView = PieChartView()
        pieChartView.backgroundColor = UIColor.white
        return pieChartView
    }()
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.clear
        //添加控件
        addSubView(pieChartView)
        //layout
        self.pieChartView.snp.makeConstraints { (make) in
            make.left.equalTo(self)
            make.top.equalTo(self.).offset(10)
            make.right.equalTo(self)
            make.height.equalTo(250)
        }
        //设置饼状图数据
        setChart(dataPoints: months, values: unitsSold)
    }
    

2.设置饼状图的数据

func setChart(dataPoints: [String], values: [Double]) {
        var dataEntries: [ChartDataEntry] = []
        for i in 0..<dataPoints.count {
            let entry = PieChartDataEntry(value: values[i], label: "\(dataPoints[i])") //设置数据 title和对应的值
            
            dataEntries.append(entry)
        }
        
        
        let pichartDataSet = PieChartDataSet(values: dataEntries, label: "") //设置表示
        //设置饼状图字体配置
        setPieChartDataSetConfig(pichartDataSet: pichartDataSet)
        
        
        let pieChartData = PieChartData(dataSet: pichartDataSet)
        //设置饼状图字体样式
        setPieChartDataConfig(pieChartData: pieChartData)
        pieChartView.data = pieChartData //将配置及数据添加到表中
        
        
        //设置饼状图样式
        setDrawHoleState()
        pichartDataSet.colors = [MYCOlOR(r: 50, g: 161, b: 127, a: 1.0),MYCOlOR(r: 45, g: 90, b: 160, a: 1.0),MYCOlOR(r: 206, g: 89, b: 90, a: 1.0)]//设置区块颜色
    }
    

3.设置饼状图每一个块对应的数据的属性

 //设置饼状图字体配置
    func setPieChartDataSetConfig(pichartDataSet: PieChartDataSet){
        pichartDataSet.sliceSpace = 0 //相邻区块之间的间距
        pichartDataSet.selectionShift = 1 //选中区块时, 放大的半径
        pichartDataSet.xValuePosition = .insideSlice //名称位置
        pichartDataSet.yValuePosition = .outsideSlice //数据位置
        //数据与区块之间的用于指示的折线样式
        pichartDataSet.valueLinePart1OffsetPercentage = 0.85 //折线中第一段起始位置相对于区块的偏移量, 数值越大, 折线距离区块越远
        pichartDataSet.valueLinePart1Length = 0.5 //折线中第一段长度占比
        pichartDataSet.valueLinePart2Length = 0.4 //折线中第二段长度最大占比
        pichartDataSet.valueLineWidth = 1 //折线的粗细
        pichartDataSet.valueLineColor = UIColor.lightGray //折线颜色
    }

4.设置百分比数据的属性,这里自定义了一个类DigitValueFormatter(),只要实现了他的协议就行了

//设置饼状图字体样式
    func setPieChartDataConfig(pieChartData: PieChartData){
        pieChartData.setValueFormatter(DigitValueFormatter())//设置百分比
        pieChartData.setValueTextColor(UIColor.gray) //字体颜色为白色
        pieChartData.setValueFont(UIFont.systemFont(ofSize: 10))//字体大小
    }

    
//数值转化成百分比
public class DigitValueFormatter: NSObject, IValueFormatter {
    public func stringForValue(_ value: Double, entry: ChartDataEntry, dataSetIndex: Int, viewPortHandler: ViewPortHandler?) -> String {
        let valueWithoutDecimalPart = String(format: "%.2f%%", value)
        return valueWithoutDecimalPart
        
    }
}
    

5.最后是整个饼状图视图的属性设置

    //设置饼状图中心文本
    func setDrawHoleState(){
        ///饼状图距离边缘的间隙
        pieChartView.setExtraOffsets(left: 30, top: 0, right: 30, bottom: 0)
        //拖拽饼状图后是否有惯性效果
        pieChartView.dragDecelerationEnabled = false
        //是否显示区块文本
        pieChartView.drawSlicesUnderHoleEnabled = true
        //是否根据所提供的数据, 将显示数据转换为百分比格式
        pieChartView.usePercentValuesEnabled = true
        
        // 设置饼状图描述
        pieChartView.chartDescription?.text = "本年度项目情况"
        pieChartView.chartDescription?.font = UIFont.systemFont(ofSize: 10)
        pieChartView.chartDescription?.textColor = UIColor.gray
        
        // 设置饼状图图例样式
        pieChartView.legend.maxSizePercent = 0.9 //图例在饼状图中的大小占比, 这会影响图例的宽高
        pieChartView.legend.formToTextSpace = 5 //文本间隔
        pieChartView.legend.font = UIFont.systemFont(ofSize: 10) //字体大小
        pieChartView.legend.textColor = UIColor.gray //字体颜色
        pieChartView.legend.verticalAlignment = .bottom //图例在饼状图中的位置
        pieChartView.legend.form = .circle //图示样式: 方形、线条、圆形
        pieChartView.legend.formSize = 12 //图示大小
        pieChartView.legend.orientation = .horizontal
        pieChartView.legend.horizontalAlignment = .center
        
        
        ///设置饼状图中心的文本
        if pieChartView.isDrawHoleEnabled {
            ///设置饼状图中间的空心样式
            pieChartView.drawHoleEnabled = true //饼状图是否是空心
            pieChartView.holeRadiusPercent = 0.3 //空心半径占比
            pieChartView.holeColor = UIColor.white //空心颜色
            pieChartView.transparentCircleRadiusPercent = 0.32 //半透明空心半径占比
            //半透明空心的颜色
            pieChartView.transparentCircleColor = MYCOlOR(r: 210, g: 145, b: 165, a: 0.3)
            pieChartView.drawCenterTextEnabled = false //是否显示中间文字
            //普通文本
            pieChartView.centerText = "平均库龄"
            //富文本
            //         let attributes = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: CGFloat(15.0)), NSForegroundColorAttributeName: UIColor.red]
            //         let centerTextAttribute = NSAttributedString(string: "平均库龄", attributes: attributes)
            //         pieChartView.centerAttributedText = centerTextAttribute
        }
 
        
        pieChartView.setNeedsDisplay()
        
        
    }

柱状图

柱状图

柱状图和饼状图稍微不一样,我这里是做的3个一组的柱状图,看了一下午的demo终于稍微明白到底咋搞的老。

1.实历化柱状图,在写柱状图的过程中发现属性设置也可以在初始化的时候设置,另外还新定义了横向(DayAxisValueFormatter)和纵向(MoneyAxisValueFormatter)的格式化的类

var chartView:BarChartView = {
        let chartView = BarChartView(frame: CGRect.zero)
        ///饼状图距离边缘的间隙
        chartView.setExtraOffsets(left: 10, top: 10, right: 30, bottom: 0)
        //拖拽饼状图后是否有惯性效果
        chartView.dragEnabled = false
        //设置是否支持缩放
        chartView.setScaleEnabled(false)
        // 设置饼状图描述
//        chartView.chartDescription?.text = "本年度项目情况"
//        chartView.chartDescription?.font = UIFont.systemFont(ofSize: 10)
//        chartView.chartDescription?.textColor = UIColor.gray
        chartView.chartDescription?.enabled = false
        
        //设置x坐标数据样式
        let xAxis = chartView.xAxis
        xAxis.labelPosition = .bottom
        xAxis.labelFont = .systemFont(ofSize: 10)
        xAxis.valueFormatter = DayAxisValueFormatter()
        
        //设置y坐标数据样式
        let leftAxis = chartView.leftAxis
        leftAxis.labelFont = .systemFont(ofSize: 10)
        leftAxis.labelCount = 8
        leftAxis.valueFormatter = MoneyAxisValueFormatter()
        //设置字体显示在图表之外
        leftAxis.labelPosition = .outsideChart
        //从坐标原点开始
        leftAxis.axisMinimum = 0 // FIXME: HUH?? this replaces startAtZero = YES
        //设置右边坐标不显示
        chartView.rightAxis.enabled = false
        return chartView
    }()

2.横向(DayAxisValueFormatter)和纵向(MoneyAxisValueFormatter)的格式化的类也很简单实现一个协议就好了

public class DayAxisValueFormatter: NSObject, IAxisValueFormatter {
    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        //这里的int不一定返回的是1,2,3所以显示的数据可能有误。
        let days = Int(value)
        return String(format:"201\(7+days)年")
    }
}

public class MoneyAxisValueFormatter: NSObject, IAxisValueFormatter {
    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        let days = Int(value) + 1
        return String(format:"\(days)¥")
    }
}

3.设置柱状图的数据

    func setDataCount(_ count: Int, range: UInt32) {
        let groupSpace = 0.2
        let barSpace = 0
        let barWidth = 0.2
        // (0.2 + 0) * 4 + 0.2 = 1.00 -> interval per "group"
        
        //柱状图显示的数据值
        let randomMultiplier = range * 100
        let startYear = 1
        
        let block: (Int) -> BarChartDataEntry = { (i) -> BarChartDataEntry in
            return BarChartDataEntry(x: Double(i), y: Double(arc4random_uniform(randomMultiplier)))
        }
        //这里暂时给的临时数据里面的值是没有意义的因为没有用到
        let yVals1 = ([500,2,3,4]).map(block)
        let yVals2 = ([2,2,3,4]).map(block)
        let yVals3 = ([4,2,3,4]).map(block)
        
        let set1 = BarChartDataSet(values: yVals1, label: "项目数")
        set1.setColor(ZLGreenColor)
        
        let set2 = BarChartDataSet(values: yVals2, label: "总分")
        set2.setColor(MainColor())
        
        let set3 = BarChartDataSet(values: yVals3, label: "平均分")
        set3.setColor(ZLRedColor)
        
        let data = BarChartData(dataSets: [set1, set2, set3])
        data.setValueFont(.systemFont(ofSize: 10, weight: .light))
        //设置数据显示的格式
        data.setValueFormatter(DigitValueFormatter())
        // specify the width each bar should have
        data.barWidth = barWidth
        
        //设置图形的起始坐标注意起始坐标和你的数据相关
        chartView.xAxis.axisMinimum = Double(startYear)
//
//        // groupWidthWithGroupSpace(...) is a helper that calculates the width each group needs based on the provided parameters,计算图形x方向坐标的最大值,如果不计算的话,x坐标跑到很大,你的图形就看不到了。
//        chartView.xAxis.axisMaximum = Double(startYear) + data.groupWidth(groupSpace: groupSpace, barSpace: Double(barSpace)) * Double(groupCount)
        //设置x方向的最大横坐标,因为我的柱状图不需要缩放,所以就直接给他横向坐标的最大数。
        chartView.xAxis.axisMaximum = 5
        
        data.groupBars(fromX: Double(startYear), groupSpace: groupSpace, barSpace: Double(barSpace))
        chartView.data = data
    }