最近公司项目中要做一个报表功能,需要用到图表,于是就使用了 Charts 这个框架,这个框架可以说是图表中用的最多的框架了,由于 Charts
只有 Swift
版本,公司项目是用 OC
写的,所以先整理一下 OC
的使用方法,Swift
等以后项目转了在整理。
1. 创建 CombinedChartView 并设置属性
下面列出一些常用的设置属性,可以根据需求自行设置。
@interface CombinedChartViewController()
@property (nonatomic, strong) CombinedChartView *combinedChartView;
@end
|
@implementation CombinedChartViewController
- (void)viewDidLoad { [super viewDidLoad];
_combinedChartView = [[CombinedChartView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 350)]; _combinedChartView.drawOrder = @[@(CombinedChartDrawOrderBar), @(CombinedChartDrawOrderLine)]; _combinedChartView.noDataText = @"暂无数据"; _combinedChartView.descriptionText = @""; _combinedChartView.legend.enabled = NO; _combinedChartView.pinchZoomEnabled = NO; _combinedChartView.doubleTapToZoomEnabled = NO; _combinedChartView.scaleXEnabled = NO; _combinedChartView.scaleYEnabled = NO; _combinedChartView.scaleEnabled = NO; _combinedChartView.highlightPerTapEnabled = NO; _combinedChartView.highlightPerDragEnabled = NO; _combinedChartView.dragEnabled = YES; _combinedChartView.dragDecelerationEnabled = YES; _combinedChartView.dragDecelerationFrictionCoef = 0.5; [self.view addSubview:_combinedChartView];
ChartXAxis *xAxis = _combinedChartView.xAxis; xAxis.labelPosition = XAxisLabelPositionBottom; xAxis.drawGridLinesEnabled = NO; xAxis.axisLineColor = [UIColor lightGrayColor]; xAxis.axisLineWidth = 0.5f; xAxis.labelFont = [UIFont systemFontOfSize:10]; xAxis.labelTextColor = [UIColor lightGrayColor]; xAxis.labelRotationAngle = 30;
ChartYAxis *leftAxis = _combinedChartView.leftAxis; leftAxis.labelPosition = YAxisLabelPositionOutsideChart; leftAxis.drawGridLinesEnabled = YES; leftAxis.gridColor = [UIColor lightGrayColor]; leftAxis.gridLineWidth = 0.5f; leftAxis.drawAxisLineEnabled = NO; leftAxis.labelFont = [UIFont systemFontOfSize:10]; leftAxis.labelTextColor = [UIColor lightGrayColor]; leftAxis.axisMinimum = 0; leftAxis.axisMaximum = 500; [leftAxis setLabelCount:6 force:YES];
ChartYAxis *rightAxis = _combinedChartView.rightAxis; rightAxis.labelPosition = YAxisLabelPositionOutsideChart; rightAxis.drawGridLinesEnabled = NO; rightAxis.drawAxisLineEnabled = NO; rightAxis.labelFont = [UIFont systemFontOfSize:10]; rightAxis.labelTextColor = [UIColor lightGrayColor]; rightAxis.axisMinimum = 0; rightAxis.axisMaximum = 100; [rightAxis setLabelCount:6 force:YES]; }
@end
|
2. 设置柱状图属性
下面将设置柱状图属性与数据进行了封装。
- (BarChartData *)getBarData:(NSArray *)bar1Values bar2Values:(NSArray *)bar2Values { NSMutableArray *barEntries = [NSMutableArray array]; if (bar1Values.count == bar2Values.count) { for (int i=0; i<bar1Values.count; i++) { BarChartDataEntry *barEntry = [[BarChartDataEntry alloc] initWithX:i yValues:@[bar1Values[i], bar2Values[i]]]; [barEntries addObject:barEntry]; } } BarChartDataSet *dataSet = [[BarChartDataSet alloc] initWithValues:barEntries]; dataSet.colors = @[[UIColor greenColor], [UIColor blueColor]]; dataSet.axisDependency = AxisDependencyLeft; dataSet.drawValuesEnabled = NO; BarChartData *data = [[BarChartData alloc] initWithDataSets:@[dataSet]]; data.barWidth = 0.55f; return data; }
|
3. 设置折线图属性
下面将设置折线图属性与数据进行了封装。
- (LineChartData *)getLineData:(NSArray *)lineValues { 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]; dataSet.colors = @[[UIColor orangeColor]]; dataSet.lineWidth = 0.5f; dataSet.circleRadius = 2.5f; dataSet.circleHoleRadius = 1.5f; dataSet.circleColors = @[[UIColor orangeColor]]; dataSet.circleHoleColor = [UIColor whiteColor]; dataSet.axisDependency = AxisDependencyRight; dataSet.drawValuesEnabled = NO; dataSet.mode = LineChartModeCubicBezier; dataSet.drawFilledEnabled = YES; NSArray *shadowColors = @[(id)[[UIColor orangeColor] colorWithAlphaComponent:0].CGColor, (id)[[UIColor orangeColor] colorWithAlphaComponent:0.7].CGColor]; CGGradientRef gradient = CGGradientCreateWithColors(nil, (CFArrayRef)shadowColors, nil); dataSet.fill = [ChartFill fillWithLinearGradient:gradient angle:90.0f]; dataSet.fillAlpha = 1.0f; LineChartData *lineData = [[LineChartData alloc] initWithDataSet:dataSet]; return lineData; }
|
4. 设置图表数据
最后通过以下方法就能够设置整个图表的数据。
- (void)setXValues:(NSArray *)xValues bar1Values:(NSArray *)bar1Values bar2Values:(NSArray *)bar2Values lineValues:(NSArray *)lineValues { CombinedChartData *data = [[CombinedChartData alloc] init]; data.barData = [self getBarData:bar1Values bar2Values:bar2Values]; data.lineData = [self getLineData:lineValues]; [_combinedChartView setData:data]; ChartXAxis *xAxis = _combinedChartView.xAxis; xAxis.axisMinimum = data.xMin - 0.5f; xAxis.axisMaximum = data.xMax + 0.5f; xAxis.valueFormatter = [[ChartIndexAxisValueFormatter alloc] initWithValues:xValues]; [_combinedChartView setVisibleXRangeMaximum:7]; [_combinedChartView animateWithYAxisDuration:1.0]; [_combinedChartView notifyDataSetChanged]; }
|
另外这里有一个坑,在设置 X
轴属性的时候,有个属性是 xAxis.labelWidth
,由于图表好像是自动计算 label
大小的,设置这个属性根本没有任何作用,所以就导致当 X
轴数据文字过长时,就全部挤在一块了,为了解决这个问题,可以在设置 xAxis.valueFormatter
的时候自定义一个 valueFormatter
来设定指定宽度截取,下面是我的自定义。
CustomAxisValueFormatter.h
@interface CustomAxisValueFormatter : NSObject <IChartAxisValueFormatter>
- (instancetype)initWithValues:(NSArray *)values labelWidth:(CGFloat)labelWidth;
@end
|
CustomAxisValueFormatter.m
@interface CustomAxisValueFormatter ()
@property (nonatomic, strong) NSArray *values; @property (nonatomic, assign) CGFloat labelWidth;
@end
@implementation CustomAxisValueFormatter
- (instancetype)initWithValues:(NSArray *)values labelWidth:(CGFloat)labelWidth { self = [super init]; if (self) { _values = values; _labelWidth = labelWidth; } return self; }
- (NSString *)stringForValue:(double)value axis:(ChartAxisBase *)axis { NSString *result = @""; NSInteger index = @(value).integerValue; if (index < _values.count) { result = _values[index]; if (_labelWidth > 0) { UILabel *label = [[UILabel alloc] init]; label.font = [UIFont systemFontOfSize:10]; label.text = result; while ([label sizeThatFits:CGSizeMake(MAXFLOAT, MAXFLOAT)].width > _labelWidth) { result = [result substringToIndex:result.length - 1]; label.text = [NSString stringWithFormat:@"%@...", result]; } return label.text; } } return result; }
@end
|
这是之前设置 xAxis.valueFormatter
的方法。
xAxis.valueFormatter = [[ChartIndexAxisValueFormatter alloc] initWithValues:xValues];
|
改为自定义的方法。
xAxis.valueFormatter = [[CustomAxisValueFormatter alloc] initWithValues:xValues labelWidth:40];
|
5. 设置数据方法
图表的数据全部放入数组中,数字用 NSNumber
类型。
[self setXValues:@[@"X轴数据1", @"X轴数据2", @"X轴数据3"] bar1Values:@[@"10", @"20", @"30"] bar2Values:@[@"30", @"20", @"10"] lineValues:@[@"40", @"50", @"60"]];
|
下面是我们项目做出来的显示效果:
其实 CombinedChartView
混合图表只是将 BarChartView
柱状图和 LineChartView
折线图合在一起了,设置还是分开设置的,所以不管是柱状图还是折线图,都可以参照上面来设置。