美文网首页iOS学习资料恩美第二个APP项目iOS开发
LineChart:折线图 详解 (PNChart三方库)

LineChart:折线图 详解 (PNChart三方库)

作者: goyohol | 来源:发表于2016-12-25 18:36 被阅读1191次

    由于最近公司要求画折线图,搞得头都大了~


    不过研究一段时间后发现PNChart还挺好用的,作者人也不错哦!😁

    知乎账号 询问作者

    虽然自己不知道这是不是 真的作者,但还是蛮开心的😊😊


    而且网络上的讲解资料只是描绘了大概的谱,更详细的界面搭建和绘制则需要进一步研究、了解!!
    所以就着自己的经验,分享一下PNChart里面LineChart的细节使用!


    导入头文件

      #import <PNChart.h>
    


    (屏幕尺寸) 宏定义:

    #define kScreenWidth \
    ([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)] ? [UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale : [UIScreen mainScreen].bounds.size.width)
    
    #define kScreenHeight \
    ([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)] ? [UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale : [UIScreen mainScreen].bounds.size.height)
    

    定义全局变量:

    // 绘图数据
    NSArray * _chart_X_LabelArr;  //字符串形式
    NSArray * _chart_Y_LabelArr;  //字符串形式 或 Number类型
    



    在- (void)viewDidLoad { }里面:

      // 绘图数据
      _chart_X_LabelArr = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"]; //字符串形式
      _chart_Y_LabelArr = @[@100,@105,@150,@60,@20,@160,@290,@110,@60];    //Number类型(或字符串形式)
    


    创建绘图对象 及 相应配置:

      PNLineChart * lineChart_2 = [[PNLineChart alloc] initWithFrame:CGRectMake(0, 50 + kScreenHeight/2.f , kScreenWidth, kScreenHeight/3.f) ];
      lineChart_2.yLabelFormat = @"%1.1f";     // 格式化Y坐标
    
      lineChart_2.showCoordinateAxis = YES; // 是否显示坐标轴    (默认 不显示)
      lineChart_2.showGenYLabels = NO;
      //    lineChart_2.showLabel = NO;           //显示x、y轴的标签     (默认展示)
      lineChart_2.thousandsSeparator = YES;
    
      [lineChart_2 setYLabelColor:[UIColor redColor] ];   //y轴标签 颜色
      [lineChart_2 setXLabelColor:[UIColor blackColor]];  //x轴标签 颜 
    
      lineChart_2.yFixedValueMax = 200.f;   //y轴最大值
      lineChart_2.yFixedValueMin = 0.f;     //y轴最小值
      //Y轴 各标签的值 (一般 固定)
      [lineChart_2 setYLabels:@[@"0",@"50",@"100",@"150",@"200"] ];
      
      [lineChart_2 setXLabels:_chart_X_LabelArr];             //x轴 标签的值
    


    折线图:

      // 折线图各时刻 心率值 数据   添加
      PNLineChartData * beatData2 = [PNLineChartData new];
      beatData2.color = PNGreen;      // 折线的颜色
      beatData2.alpha = 0.7f;
      beatData2.lineWidth = 1.5f;     // 线宽
    
      beatData2.itemCount = _chart_X_LabelArr.count;    //绘制的 点数
    
      beatData2.getData = ^(NSUInteger index) {
        CGFloat yValue;
    
            yValue = [_chart_Y_LabelArr[index] floatValue];  // 转化为数值(基本类型)
    
        return [PNLineChartDataItem dataItemWithY:yValue];
      };
    
      lineChart_2.chartData = @[beatData2];        //添加好数据
    
      lineChart_2.backgroundColor = [UIColor colorWithRed:1 green:0 blue:1 alpha:0.3f];   // 设置(淡紫色)背景色
      [self.view addSubview:lineChart_2];
      [lineChart_2 strokeChart];    //绘制曲线 
    


    效果:

    效果图

    超出Y轴的值。 ( 有效显示范围 )不会显示出来,但是会绘制到哪里。


    我自己觉得的缺点:
    1.X轴最后一位标签和箭头重合,不美观!(坐标轴及有效显示范围的大小 会根据数据的内容进行变化)
    2.图形的点与X轴位置不对应。
    当然通过以下属性 可以设置好点的对应关系,但是标签值 又不对应了。

          lineChart_2.chartMarginLeft = 21.f;             //左
    

    这几个属性慎用:(反正 我没 搞懂怎么用。。。😂😂)。还望明白的同志交流、提示一下。

          lineChart_2.chartMarginLeft             //左
      //    lineChart_2.chartMarginRight          //右
      //    lineChart_2.chartMarginTop            //上
      //    lineChart_2.chartMarginBottom        //下
    





    进阶使用
    • 1.有效显示范围
      有效显示范围宽度:chartCavanWidth
      有效显示范围高度:chartCavanHeight
    • 2.协议代理的点击显示
    • 3.获得折线图各点的坐标


    PNLineChart * lineChart_1 = [[PNLineChart alloc] initWithFrame:CGRectMake(0, 30, kScreenWidth, kScreenHeight/2.f) ];
    lineChart_1.yLabelFormat = @"%1.1f";     // 格式化Y坐标
    
    //⭐️折线图形显示的  ⭐️⭐️有效范围⭐️⭐️
    lineChart_1.chartCavanWidth = 220.f;
    lineChart_1.chartCavanHeight = 200.f;
    
    lineChart_1.showGenYLabels = YES;
    lineChart_1.showLabel = YES;
    [lineChart_1 setXLabelColor:[UIColor blackColor]];
    lineChart_1.showCoordinateAxis = YES; // 是否显示坐标轴    (默认 不显示)
    
    lineChart_1.yFixedValueMax = 200.f;   //y轴最大值
    lineChart_1.yFixedValueMin = 0.f;
    //Y轴 各倍数点
    [lineChart_1 setYLabels:@[@"0",@"50",@"100",@"150",@"200" ]     ];
    //X轴 标签值数组
    [lineChart_1 setXLabels:_chart_X_LabelArr];
    
    
    //    折线图各时刻 心率值 数据   添加
    PNLineChartData * beatData = [PNLineChartData new];
    beatData.color = PNGreen;
    beatData.alpha = 0.7f;
    beatData.lineWidth = 1.5f;
    beatData.itemCount = _chart_X_LabelArr.count;    //绘制的 点数
    
    // 折线点的样式 及 大小   (⭐️醒目)
    beatData.inflexionPointStyle = PNLineChartPointStyleCircle; //数据折点格式
    beatData.inflexionPointWidth = 3.8f; //数据折点 宽度(大小)
    
    beatData.getData = ^(NSUInteger index) {
        CGFloat  yValue = [_chart_Y_LabelArr[index] floatValue];
        return [PNLineChartDataItem dataItemWithY:yValue];
    };
    lineChart_1.chartData = @[beatData];       //添加好数据
    [self.view addSubview:lineChart_1];        
    [lineChart_1 strokeChart];                 //绘制曲线
    lineChart_1.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.3];  // (浅红)背景色
    
    lineChart_1.delegate = self;  //设置协议代理
    
    
    
    // 得到  首个点 X坐标    (用于  计算 偏移度)
    NSLog(@"lineChart_1.pathPoints   %@",lineChart_1.pathPoints);  //所有的数据 (应该是 其各分段的所有数据)
    NSLog(@"[lineChart_1.pathPoints firstObject]   %@",[lineChart_1.pathPoints firstObject]);  // 取唯一的 一条线的数据
    

    打印出来的值:



    //首个点位置
    NSString * firstPoint_Str = [NSString stringWithFormat:@"%@",[[lineChart_1.pathPoints firstObject] firstObject] ];
    NSLog(@"firstPoint_Str  %@",firstPoint_Str);
    NSCharacterSet * str_first_set = [NSCharacterSet characterSetWithCharactersInString:@"{,"];
    NSLog(@"str_first_set  %@",str_first_set);
    

    打印出来的值:


    NSString * first_X_str;
    if (![firstPoint_Str isEqualToString:@"(null)"]) {    // 第一个点存在
        NSArray * iNFO_first_arr = [firstPoint_Str componentsSeparatedByCharactersInSet:str_first_set];
        first_X_str = iNFO_first_arr[1];      // 获取第一个点的X轴 坐标
        NSLog(@"iNFO_first_arr %@",iNFO_first_arr);
    }
    

    打印出来的值:



    有效范围:绘制的折线图的显示范围
    x轴起点 通过第一个点的值( [first_X_str floatValue] ) 求出
    y轴起点 通过自己创建好的Chart视图的⭐️比例关系 求出

    //有效显示范围
    float effect_V_X = [first_X_str floatValue];      //   首个点 的x轴坐标
    float effect_V_Y = beatChart_H * 0.0785f;         // (比例关系)  起始 Y位置
    float effect_V_W = lineChart_1.chartCavanWidth;   //有效范围 宽度
    float effect_V_H = lineChart_1.chartCavanHeight;  //有效范围 高度
    
    UIView * effect_V = [[UIImageView alloc] initWithFrame:CGRectMake(effect_V_X, effect_V_Y, effect_V_W, effect_V_H)];
    effect_V.backgroundColor = [UIColor colorWithRed:1 green:1 blue:0 alpha:0.3];  //(黄色)背景色
    [lineChart_1 addSubview:effect_V];
    

    效果:X、Y轴的起点确定,即可设置自己的 坐标轴

    X轴,Y轴起点 确定



    协议方法的使用:

    @interface ViewController ( ) <PNChartDelegate>
    


      //MARK:PNChart代理  点击方法
      - (void)userClickedOnLinePoint:(CGPoint)point lineIndex:(NSInteger)lineIndex {  
        NSLog(@"chosed lineIndex(线 下标) %ld",lineIndex);
      }    // 线
      - (void)userClickedOnLineKeyPoint:(CGPoint)point lineIndex:(NSInteger)lineIndex pointIndex:(NSInteger)pointIndex  {
         NSLog(@"lineIndex(第几根线):%ld       选择点的pointIndex %ld",lineIndex + 1,pointIndex);
    
         NSLog(@"X:%@     Y:%@",_chart_X_LabelArr[pointIndex],_chart_Y_LabelArr[pointIndex]);
      }    //点 
    

    效果:点击响应事件 及 其绘制的动画效果(点多(数据量大)效果更明显)


    点击响应事件:打印对应的值

    有个点(290) , 点不到~😂😂😂



    比例位置关系
    由于chart图像绘制好,放入的另一个视图及自身的比例是固定。所以计算出有效显示范围,就可以确定 X轴起始点 和 显示高度(及 Y轴结束点:最顶端 )!!
    那么我们就可以自己绘制Y轴 和 X轴的视图放置上去。

    自己绘制X轴 与 Y轴的原因:
    1.chart绘制好以后,若其需要其显示的长度大于和屏幕的宽度,就需要一个用于显示Y轴且固定好的视图;

    例子:
    属性:

    //放置折线图的scrollView  
    @property (strong, nonatomic) UIScrollView *numChart_ScrollV;
    


    绘制:

     //    UIScrollView
    float chart_Scroll_X = 0.f;
    float chart_Scroll_W = kScreenWidth;
    float chart_Scroll_H = kScreenWidth * 7/10.f;
    float chart_Scroll_Y = kScreenHeight - chart_Scroll_H - 20.f;
    self.numChart_ScrollV = [[UIScrollView alloc] initWithFrame:CGRectMake(chart_Scroll_X, chart_Scroll_Y, chart_Scroll_W, chart_Scroll_H)];
    self.numChart_ScrollV.backgroundColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.2f];  //(淡蓝色)背景色
    [self.view addSubview:self.numChart_ScrollV];
    self.numChart_ScrollV.scrollEnabled = YES;  //可滑动
    
    // Chart设置为 两倍屏宽
    PNLineChart * lineChart_1 = [[PNLineChart alloc] initWithFrame:CGRectMake(0, 0, 2 * kScreenWidth, chart_Scroll_H) ];
    // ScrollView的显示范围      
    self.numChart_ScrollV.contentSize = CGSizeMake(lineChart_1.frame.size.width, lineChart_1.frame.size.height);
    
    //折线图形显示的有效范围
    lineChart_1.chartCavanWidth = 500.f;
    lineChart_1.chartCavanHeight = 160.f;
    
    [self.numChart_ScrollV addSubview:lineChart_1];
    

    效果:Y轴不固定



    所以确定 起点的X轴坐标 及 有效显示范围的上面那条边对应 顶点的Y值(Y轴显示标签最大值) 就可以了。


    2.X轴里面的标签值的字符串长度过大,并不会自适应宽度,所有最好自定制一个X轴的视图。

    例子:

      // 把X轴的数据的长度     更改 过大
      _chart_X_LabelArr = @[@"100",@"2",@"3333.232",@"4004",@"55",@"6666.66",@"7777",@"8888.8888",@"99"]; 
    

    效果:显示的大小不统一且出现了换行。



    位置关系的总结
    由于与父视图左侧、顶部 重合。放入的绘图数据 变化时,其显示的Y轴最大标签值 的顶部 到父视图顶部距离固定。计算出其距离可确定有效范围(黄色区域)的起点,即可知道Y轴的位置了。

    有效范围的X轴起点坐标:从第一个点的坐标获取;
    有效范围的Y轴起点坐标:根据 放置自己的Chart高度的比例,就可计算出其值。(Chart高度固定(或 比例确定),有效范围的Y轴标签的顶点坐标 即固定)
    ⭐️由于ScrollView和Chart的视图位置、大小关系固定,即可在ScrollView或者在Chart里面添加自己绘制的X轴坐标的视图。



    我自己公司项目里面没使用LineChart自带的坐标轴,全部自己绘制。主要是其坐标轴:1.在适配时,比例不一;2.在(X轴 坐标)数据量不同时,比例也不一致。就自己根据位置、比例关系,计算好位置 并 放置上X轴与Y轴(⭐️放置在self.view上,且置于最顶层)的自定制视图。

    自己只顾到了位置上的效果!
    如果什么地方有悖于作者原本的思想,还望指出!谢谢~
















    goyohol's essay

    相关文章

      网友评论

      • 想想8606:请问,我这边需求是折线和x轴都可以滑动,但是y轴要固定不动,这个怎么实现呢
        goyohol:@想想8606 根据放入的数据计算好相对于屏幕的宽度及高度(固定),放在SCrollview上
      • 虞小虞:大神请问一下,用PNChart绘制条形图的时候,怎么样才能用跟折线图一样用2个数组进行绘制?
        goyohol:不好意思,整理文章时才看到。。 我记得当时是 创建多个放在一个SCrollview上
      • Yokihr:有demo么
      • Just_go:为什么不用Charts, 这个估计也是抄的Charts
        goyohol:@特拉法尔咖 oc版的
        特拉法尔咖:Charts是Swift的吧?有OC版本吗?
        goyohol:@Just_go 公司叫用这个 我没办法。。 但是这个也比较火~
      • goyohol:公司项目赶,自己只关乎效果!!但是更要“知其所以然”。
        所以:

        showGenYLabels属性 自己也不明白。。 有明白的朋友指点一下。O(∩_∩)O谢谢~~~

      本文标题:LineChart:折线图 详解 (PNChart三方库)

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