OC调用Charts绘制图表--LineChart

之前一直都说要写关于绘制折线和柱状图的相关文章,之前在忙新的项目,这几天不忙,也是之前那篇文章有小伙伴问我折线与柱状图绘制的相关问题,说一些自己研究Charts的经验,仅代表个人观点,如有错误,请多指正,下面进入正题。
首先看一下目前折线图的效果


OC调用Charts绘制图表--LineChart_第1张图片
多系列折线图.png

这个效果是经历了将近一个月的时间,为了有这样的效果,我翻遍了的文章,问了很多人,技术群,这个效果是在产品经理每周叨叨叨逼出来的,不要问我为什么这么说,真的是每天都追着我改改改,优化优化优化,所以现在就有了这样的效果,下面是代码,代码里面该标注释的地方都有注释,不要问我有github链接么,所有代码都在这里,试试就知道了,讲真,我不骗人,毕竟试试又不会怀孕~~

声明一下绘制的LineChartView只有左Y轴,没有右Y轴,右Y轴设置也很简单,请参考左Y轴,但是一般只要左Y轴就好了。
首先是初始化,喜欢用懒加载初始化,因为页面有好几个图表,第一时间不一定用得到折线图,初始化只有一句话,是不是很爽,别想太多,因为好几个模块用到的东西都一样,就放在一个工具类里面了,MBSChartTool这个工具类,有文章,全是代码以及注释。。。这个工具类只是为了偷懒,最后控制器还有遵守一个代理

@interface ViewController ()
@property (nonatomic, strong) LineChartView *lineChartView;
@end

#pragma mark - getter and setter
- (LineChartView *)lineChartView
{
    if (_lineChartView == nil) {
        
        _lineChartView = [MBSChartTool lineChartViewForLeftWithDelegate:self];

    }
    return _lineChartView;
}
- (NSArray *)colorArray
{
    if (_colorArray == nil) { //橘黄色  蓝色 淡绿色 浅紫色 浅红色
        _colorArray = @[ RGB(242, 152, 80), RGB(92, 178, 240), RGB(158, 202, 97), RGB(219, 95, 153), RGB(233, 84, 83)];
    }
    return _colorArray;
}
- (NSArray *)xTitles
{
    if (_xTitles == nil) {
        
        _xTitles = @[@"第1周", @"第2周", @"第3周", @"第4周", @"第5周"];
    }
    return _xTitles;
}
添加LinechartView 与 设置LinechartData
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view addSubview:self.lineChartView];
    [self.lineChartView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(self.view).insets(UIEdgeInsetsMake(10, 20, 10, 10));
    }];
    [self setData];
}
- (void)setData
{
    NSArray *array = @[@"5553.8", @"5959.3", @"1961.7", @"", @""];
    NSArray *array1 = @[@"998.5", @"1014.5", @"249", @"", @""];
    NSMutableArray *valueArray = [NSMutableArray array];
    [valueArray addObject:array];
    [valueArray addObject:array1];

    NSMutableArray *dataSets = [NSMutableArray array];
    double leftAxisMin = 0;
    double leftAxisMax = 0;
    for (int i = 0; i < valueArray.count; i++) {
        
        NSArray *values = valueArray[i];
        NSMutableArray *yVals = [NSMutableArray array];
        NSString *legendName = [NSString stringWithFormat:@"第%d个图例", i];
        for (int i = 0; i < values.count; i++)
        {
            NSString *valStr = [NSString stringWithFormat:@"%@", values[i]];
            double val = [valStr doubleValue];
            leftAxisMax = MAX(val, leftAxisMax);
            leftAxisMin = MIN(val, leftAxisMax);
            ChartDataEntry *entry = [[ChartDataEntry alloc] initWithX:i y:val];
            [yVals addObject:entry];
        }
        
        LineChartDataSet *dataSet = [[LineChartDataSet alloc] initWithValues:yVals label:legendName];
        dataSet.lineWidth = 3.0f;//折线宽度
        dataSet.drawValuesEnabled = YES;//是否在拐点处显示数据
        dataSet.valueColors = @[self.colorArray[i]];//折线拐点处显示数据的颜色
        [dataSet setColor:self.colorArray[i]];//折线颜色
        dataSet.drawSteppedEnabled = NO;//是否开启绘制阶梯样式的折线图
        dataSet.drawCirclesEnabled = NO;//是否绘制拐点
        dataSet.circleRadius = 3.0f;//拐点半径
        dataSet.axisDependency = AxisDependencyLeft;
        dataSet.drawCircleHoleEnabled = YES;//是否绘制中间的空心
        dataSet.circleHoleRadius = 1.0f;//空心的半径
        dataSet.circleHoleColor = self.colorArray[i];//空心的颜色
        dataSet.highlightEnabled = YES;//选中拐点,是否开启高亮效果(显示十字线)
        dataSet.highlightColor = [UIColor clearColor];
        dataSet.valueFont = [UIFont systemFontOfSize:12];
        [dataSets addObject:dataSet];
    }
    
    double leftDiff = leftAxisMax - leftAxisMin;
    if (leftAxisMax == 0 && leftAxisMin == 0) {
        leftAxisMax = 100.0;
        leftAxisMin = -10.0;
    } else {
        leftAxisMax = (leftAxisMax + leftDiff * 0.2);
        leftAxisMin = (leftAxisMin - leftDiff * 0.1);
    }
    self.lineChartView.leftAxis.axisMaximum = leftAxisMax;
    self.lineChartView.leftAxis.axisMinimum = leftAxisMin;
    LineChartData *data = [[LineChartData alloc] initWithDataSets:dataSets];
    self.lineChartView.data = nil;
    self.lineChartView.xAxis.axisMinimum = -0.8;
    self.lineChartView.xAxis.axisMaximum = 5.1;
    self.lineChartView.data = data;
    [self.lineChartView animateWithXAxisDuration:0.3f];
}
x轴数据源方法
lineChartView.xAxis.valueFormatter = target; 
这句话如果设置了,就必须实现x轴的数据源方法
- (NSString *)stringForValue:(double)value axis:(ChartAxisBase *)axis
{
    return self.xTitles[(int)value % self.monthTitles.count];
}
xTitles就是你需要在x轴展现的标题数组,赋值就这么写就好,别问为什么,英语好的点进去看看就知道了,四级过了英语就不看了。

这样就会有出现下面的多系列折线图


OC调用Charts绘制图表--LineChart_第2张图片
不完美的多系列折线图.png

你看见x轴的标题多了一个,强迫症受不了,产品经理看见也难受,所以要改正这个,其实这样的图表还是好的,看一下最初不知道设置零起点与x轴时的折线图。


OC调用Charts绘制图表--LineChart_第3张图片
看着受不了的折线图.png

这样的折线图,看着更加让人难受,这就是最初不知道方法不知道如何解决时的折线图,但是我那时候想到一个曲线救国的方法,就是在xtitles最前面添加俩个空的字符串,在赋值的时候把i变成了i+2,这样虽然不是很完美,但是基本解决零起点问题,也不至于让产品天天盯着你改改改,后来自己决定这样不是问题,就去看demo,找到了新的解决办法,当初步解决的时候,高兴的我那感觉真的无法形容,就是可以在产品问你改好了么时候,你可以得意看着他,说一句哥改好了。说正事,方法如下:

曲线救国方法(可以忽略):   
ChartDataEntry *entry = [[ChartDataEntry alloc] initWithX:i + 2 y:val];
正确方法:
self.lineChartView.xAxis.axisMinimum = -0.8;    
self.lineChartView.xAxis.axisMaximum = 5.1;

因为x标题数组较少,所有就这么写了,标准的方法:
self.lineChartView.xAxis.axisMinimum = data.xMin - 0.8;            
self.lineChartView.xAxis.axisMaximum = data.xMax + 0.8;

采用标准方法修复x轴最小值与最大值问题效果如之前不完美的折线图


OC调用Charts绘制图表--LineChart_第4张图片
不完美的多系列折线图.png

这样虽然距离左右轴美观了,但是有重复问题,我目前也没有找到直接解决问题的办法,但是可以采用方法折线图的方法间接解决此问题,放大折线图之后不让进行缩放与拖动,如果你够耐心的话,可以继续调试ineChartView.xAxis.axisMaximum和lineChartView.xAxis.axisMinimum这俩个属性,达到一个理想的状态,方法折线图方法如下:

[_lineChartView zoomWithScaleX:1.03 scaleY:1 x:0 y:0];

放大的方法有了,又会遇到新的问题,方法的比例是多少,这个好解决,折线图有个代理方法,添加代理方法,手动进行缩放,打印里面的放大比例,然后把这个值填进去就是你需要的,不要问我为什么这么机智,逼出来的

#pragma mark - ChartView Delegate
- (void)chartScaled:(ChartViewBase *)chartView scaleX:(CGFloat)scaleX scaleY:(CGFloat)scaleY
{
    NSLog(@"%2f %2f", scaleX, scaleY);
}

还有一些其他的属性和方法,想到那个写那个

//缩放重置  
 [_lineChartView zoomOut];
// 可以设置dataset依赖左Y轴还是右Y轴,有的时候左右y轴的大小值不一样,可以进行这么设置
dataSet.axisDependency = AxisDependencyLeft;
//   多系列折线图数据初始化  
 LineChartData *data = [[LineChartData alloc] initWithDataSets:dataSets];
//   单系列折线图数据初始化
 LineChartData *data = [[LineChartData alloc] initWithDataSet:dataSet];

经历了半个月的煎熬,对于折线图x轴标题重复的问题得到了完美的解决,只需要一个属性,上面的话没有删除,全当自己灵活变通的思路了,也做为一个对自己的警醒,明明是一个属性的设置,却因为抵触情绪不知道尝试,下面说正事

 lineChartView.xAxis.granularity = 1.0;

看下这个属性的charts的解释

/**
  The minimum interval between axis values.
  This can be used to avoid label duplicating when zooming in.
  default: 1.0
*/
@property (nonatomic) double granularity;

百度翻译加自己的理解一下大概意思就是:
x轴标题中间最小的间隔。这样可以避免在缩放时label文字重复。

然后在设置x轴大小的时候就可以使用通用的方法:

self.lineChartView.xAxis.axisMinimum = data.xMin - 0.8;      self.lineChartView.xAxis.axisMaximum = data.xMax + 0.8;

这样x轴标题重复的问题就完美解决了,也不用跟产品和测试撕逼了。
折线图暂时想的问题和解决办法就这么多,如有不对的地方还请多指教
最后demo地址,欢迎大家下载,最好给个star

你可能感兴趣的:(OC调用Charts绘制图表--LineChart)