iOS使用Charts 混合柱状图开发

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


~混合柱子~

我们使用的是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,欢迎交流讨论~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 晚饭过后,凉风习习,恰逢周末。踏上单车,塞上耳机,身披夕阳余晖,一路蹬到开远市滇南发电总厂——是的,就是那个7路、...
    聆听_自然阅读 259评论 0 0
  • 封建社会是绝对的男权社会,男人一直试图禁锢女性的思想,以三从四德要求她们,似乎很怕妇女变成独立自主的个体,但有些东...
    常晴空阅读 1,981评论 0 3
  • 因为本人要去泸沽湖玩几天,所以停更大概三天左右。 希望一直支持我的朋友能够理解。 谢谢。 ...
    大作家史努比阅读 158评论 2 0