美文网首页iOS DeveloperiOS开发你需要知道的
iOS使用Charts 混合柱状图开发

iOS使用Charts 混合柱状图开发

作者: coolLee | 来源:发表于2017-04-12 10:24 被阅读2091次

    近期公司的产品有新的需求,大概效果就如下所示:


    ~混合柱子~

    我们使用的是ios-charts这个第三方,但是在网上找了一大堆也没有发现这种效果的柱状图,没办法只能自己操刀来实现了。实现过程中借鉴了安卓中的MPCharts类似效果的实现方法,话不多说,直接上代码,代码中注释已经比较清晰了,有不懂得欢迎咨询。
    我是写了一个这种效果实现的工具类,在.h文件中申明方法:

    /**
     两根柱子以及折线的混合显示
    
     @param combineChart 需要设置的CombineChartView
     @param xValues X轴的值数组,里面放字符串
     @param lineValues 折线值数组
     @param bar1Values 柱子1的值数组
     @param bar2Values 柱子2的值数组
     @param lineTitle 图例中折线的描述
     @param bar1Title 图例中柱子1的描述
     @param bar2Title 图例中柱子2的描述
     
     warning:由于绘制有顺序,所以绘制高柱子应该在绘制低柱子之前进行,所以bar1Values中的值要大于对应的bar2Values中的值,绘制折线应该在最后进行
     */
    - (void)setCombineBarChart:(CombinedChartView *)combineChart xValues:(NSArray *)xValues lineValues:(NSArray *)lineValues bar1Values:(NSArray *)bar1Values bar2Values:(NSArray *)bar2Values lineTitle:(NSString *)lineTitle bar1Title:(NSString *)bar1Title bar2Title:(NSString *)bar2Title;
    

    在.m文件中实现这个方法:

    - (void)setCombineBarChart:(CombinedChartView *)combineChart xValues:(NSArray *)xValues lineValues:(NSArray *)lineValues bar1Values:(NSArray *)bar1Values bar2Values:(NSArray *)bar2Values lineTitle:(NSString *)lineTitle bar1Title:(NSString *)bar1Title bar2Title:(NSString *)bar2Title
    {
        combineChart.descriptionText = @"";
        combineChart.pinchZoomEnabled = YES;
        combineChart.marker = [[ChartMarkerView alloc] init];
        combineChart.drawOrder = @[@0,@0,@2];//CombinedChartDrawOrderBar,CombinedChartDrawOrderLine 绘制顺序
        combineChart.doubleTapToZoomEnabled = NO;//取消双击放大
        combineChart.scaleYEnabled = NO;//取消Y轴缩放
        combineChart.dragEnabled = YES;//启用拖拽图表
        combineChart.dragDecelerationEnabled = YES;//拖拽后是否有惯性效果
        combineChart.dragDecelerationFrictionCoef = 0.9;//拖拽后惯性效果的摩擦系数(0~1),数值越小,惯性越不明显
        combineChart.highlightPerTapEnabled = NO;//取消单击高亮显示
        combineChart.highlightPerDragEnabled = NO;//取消拖拽高亮
        ChartXAxis *xAxis = combineChart.xAxis;
        xAxis.labelPosition = XAxisLabelPositionBottom;
        xAxis.drawGridLinesEnabled = NO;
        xAxis.labelFont = [UIFont systemFontOfSize:15];
        xAxis.labelCount = xValues.count;
        xAxis.labelRotationAngle = -40;
        
        xAxis.valueFormatter = [[ChartIndexAxisValueFormatter alloc] initWithValues:xValues];//设置X轴显示的值
        
        //左侧Y轴设置
        ChartYAxis *leftAxis = combineChart.leftAxis;
        leftAxis.labelPosition = YAxisLabelPositionOutsideChart;
        leftAxis.axisMinimum = 0.0f;
        leftAxis.drawGridLinesEnabled = YES;
        
        float yMin = [[bar2Values valueForKeyPath:@"@min.floatValue"] floatValue]*0.9;
        float yMax = [[bar1Values valueForKeyPath:@"@max.floatValue"] floatValue]*1.1;
        leftAxis.axisMinimum = yMin;
        leftAxis.axisMaximum = yMax;
    
        //右侧Y轴
        ChartYAxis *rightAxis = combineChart.rightAxis;
        rightAxis.labelPosition = YAxisLabelPositionOutsideChart;
        rightAxis.drawGridLinesEnabled = NO;
        rightAxis.axisMinimum = 0;
        rightAxis.axisMaximum = 100;
        //设置图例
        ChartLegend *legend = combineChart.legend;
        legend.horizontalAlignment = ChartLegendHorizontalAlignmentLeft;
        legend.verticalAlignment = ChartLegendVerticalAlignmentBottom;
        legend.orientation = ChartLegendOrientationHorizontal;
        legend.drawInside = NO;
        legend.direction = ChartLegendDirectionLeftToRight;
        legend.form = ChartLegendFormSquare;
        legend.formSize = 12;
        //设置数据
        CombinedChartData *data = [[CombinedChartData alloc] init];
        data.lineData = [self generateLineData:lineValues lineTitle:lineTitle];
        data.barData = [self generateCombineBarData:bar1Values bar2Values:bar2Values title1:bar1Title title2:bar2Title];
        combineChart.data = data;
        
        
        //让柱子在X轴显示全
        xAxis.axisMinimum = data.xMin - 1.0f;
        xAxis.axisMaximum = data.xMax + 1.0f;
        combineChart.extraBottomOffset = 10;
        combineChart.extraTopOffset = 30;
        [combineChart animateWithYAxisDuration:1.0];//添加Y轴动画
    }
    //生成折线的数据
    - (LineChartData *)generateLineData:(NSArray *)lineValues lineTitle:(NSString *)lineTitle
    {
        NSMutableArray *entries = [NSMutableArray array];
        for (int i = 0; i < lineValues.count; i++) {
            ChartDataEntry *entry = [[ChartDataEntry alloc] initWithX:i y:[lineValues[i] floatValue]];
            [entries addObject:entry];
        }
        
        LineChartDataSet *dataSet = [[LineChartDataSet alloc] initWithValues:entries label:lineTitle];
        dataSet.colors = @[[UIColor greenColor]];
        dataSet.lineWidth = 2.5f;
        dataSet.circleColors = @[[UIColor redColor]];
        dataSet.circleHoleColor = [UIColor purpleColor];
        dataSet.axisDependency = AxisDependencyRight;
        dataSet.drawValuesEnabled = YES;//不绘制线的数据
        
        LineChartData *lineData = [[LineChartData alloc] initWithDataSet:dataSet];
        [lineData setValueFont:[UIFont systemFontOfSize:10]];
        
        return lineData;
    }
    //生成复杂的组合柱图的数据(两根重叠的柱和折线的图)
    - (BarChartData *)generateCombineBarData:(NSArray *)bar1Values bar2Values:(NSArray *)bar2Values title1:(NSString *)bar1Title title2:(NSString *)bar2Title
    {
        NSMutableArray *bar1Entries = [NSMutableArray array];
        NSMutableArray *bar2Entries = [NSMutableArray array];
        for (int i=0; i<bar1Values.count; i++) {
            BarChartDataEntry *barEntry = [[BarChartDataEntry alloc] initWithX:i y:[bar1Values[i] floatValue]];
            [bar1Entries addObject:barEntry];
        }
        for (int i=0; i<bar2Values.count; i++) {
            BarChartDataEntry *barEntry = [[BarChartDataEntry alloc] initWithX:i y:[bar2Values[i] floatValue]];
            [bar2Entries addObject:barEntry];
        }
        
        BarChartDataSet *dataSet1 = [[BarChartDataSet alloc]  initWithValues:bar1Entries label:bar1Title];
        dataSet1.colors = @[[UIColor grayColor]];
        dataSet1.valueColors = @[[UIColor orangeColor]];
        dataSet1.axisDependency = AxisDependencyLeft;
        dataSet1.drawValuesEnabled = NO;
        
        BarChartDataSet *dataSet2 = [[BarChartDataSet alloc]  initWithValues:bar2Entries label:bar2Title];
        dataSet2.colors = @[[UIColor brownColor]];
        dataSet2.valueColors = @[[UIColor orangeColor]];
        dataSet2.axisDependency = AxisDependencyLeft;
        dataSet2.drawValuesEnabled = NO;
        BarChartData *data = [[BarChartData alloc] initWithDataSets:@[dataSet1,dataSet2]];
        [data setValueFont:[UIFont systemFontOfSize:10]];
        data.barWidth = 0.9f;
        return data;
    }
    
    

    要使用这个工具类也很简单,在需要的控制器中引入这个工具类,实现如下方法:

    - (void)createCombineBarChartView
    {
        CombinedChartView *combine = [[CombinedChartView alloc] init];
        self.combineChartView = combine;
        combine.frame = CGRectMake(0, KScreenHeight/2, KScreenWidth, KScreenHeight/2);
        combine.backgroundColor = [UIColor colorWithRed:230/255.0f green:253/255.0f blue:253/255.0f alpha:1];
        [self.view addSubview:combine];
        
        //我自己的工具类
        BarChartsHelper *helper = [[BarChartsHelper alloc] init];
        [helper setCombineBarChart:self.combineChartView xValues:self.xStrings lineValues:@[@"30",@"10",@"50",@"30",@"60"] bar1Values:@[@"80",@"40",@"60",@"30",@"70"] bar2Values:@[@"60",@"30",@"53",@"20",@"45"] lineTitle:@"line" bar1Title:@"bar1" bar2Title:@"bar2"];
    }
    

    其中有个注意点就是:因为柱和线的绘制是有先后顺序的。所以要让bar1Values中的值大于bar2Values中对应的值,这样才不会被遮挡住。
    还有设置的lineTitle、bar1Title、bar2Title都是图例中的对应的描述。
    代码已经放在GitHub上https://github.com/coolLeee/LGBarCharts,欢迎交流讨论~

    相关文章

      网友评论

        本文标题:iOS使用Charts 混合柱状图开发

        本文链接:https://www.haomeiwen.com/subject/luopattx.html