OC调用Charts绘制图表--LineChart

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


多系列折线图.png

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

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

@interface ViewController ()<ChartViewDelegate>
@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", @"<null>", @"<null>"];
    NSArray *array1 = @[@"998.5", @"1014.5", @"249", @"<null>", @"<null>"];
    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轴展现的标题数组,赋值就这么写就好,别问为什么,英语好的点进去看看就知道了,四级过了英语就不看了。

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


不完美的多系列折线图.png

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


看着受不了的折线图.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轴最小值与最大值问题效果如之前不完美的折线图


不完美的多系列折线图.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.
  <em>default</em>: 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😁

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

推荐阅读更多精彩内容