当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS 折线图、柱状图的简单实现

iOS 折线图、柱状图的简单实现

2018年12月04日  | 移动技术网移动技术  | 我要评论

首先我得感谢某位博主,非常抱歉,因为之前直接下载博主提供这篇文章的demo,然后去研究了,没记住博主的名字。再次非常感谢。

而这个dome我又修改了一些,完善了一些不美观的bug,当然还有,后面会陆续更新。

1 、一开始需要给坐标轴初始一个画布

//初始化画布
+(instancetype)initwithframe:(cgrect)frame{
    //找到名称叫beziercurveview的xib视图
    beziercurveview *beziercurveview = [[nsbundle mainbundle] loadnibnamed:@"beziercurveview" owner:self options:nil].lastobject;
    beziercurveview.frame = frame;
    
    //背景视图
    uiview *backview = [[uiview alloc] initwithframe:cgrectmake(0, 0, frame.size.width, frame.size.height)];
    backview.backgroundcolor = xyqcolor(255, 229, 239);
    [beziercurveview addsubview:backview];
    
    myframe = frame;
    return beziercurveview;
}

2、然后画坐标轴,包括x、y轴的直线、箭头、字符串的索引、路径的渲染。

/**
 *  画坐标轴
 */
-(void)drawxyline:(nsmutablearray *)x_names adddistancevalues:(nsinteger )adddistance startingvalues:(nsinteger)starting proportionvaluess:(nsinteger)proportion{
    
    uibezierpath *path = [uibezierpath bezierpath];
    
    //1.y轴、x轴的直线
    [path movetopoint:cgpointmake(margin+adddistance, cgrectgetheight(myframe)-margin)];
    [path addlinetopoint:cgpointmake(margin+adddistance, margin)];
    
    [path movetopoint:cgpointmake(margin+adddistance, cgrectgetheight(myframe)-margin)];
    [path addlinetopoint:cgpointmake(margin+cgrectgetwidth(myframe)-2*margin+adddistance, cgrectgetheight(myframe)-margin)];
    
    //2.添加箭头
    [path movetopoint:cgpointmake(margin+adddistance, margin)];
    [path addlinetopoint:cgpointmake(margin-5+adddistance, margin+5)];
    [path movetopoint:cgpointmake(margin+adddistance, margin)];
    [path addlinetopoint:cgpointmake(margin+5+adddistance, margin+5)];
    
    [path movetopoint:cgpointmake(margin+cgrectgetwidth(myframe)-2*margin+adddistance, cgrectgetheight(myframe)-margin)];
    [path addlinetopoint:cgpointmake(margin+cgrectgetwidth(myframe)-2*margin-5+adddistance, cgrectgetheight(myframe)-margin-5)];
    [path movetopoint:cgpointmake(margin+cgrectgetwidth(myframe)-2*margin+adddistance, cgrectgetheight(myframe)-margin)];
    [path addlinetopoint:cgpointmake(margin+cgrectgetwidth(myframe)-2*margin-5+adddistance, cgrectgetheight(myframe)-margin+5)];

    //3.添加索引格
    //x轴
    for (int i=0; i<x_names.count; i++) {
        cgfloat x = margin + margin*(i+1);
        cgpoint point = cgpointmake(x+adddistance,cgrectgetheight(myframe)-margin);
        [path movetopoint:point];
        [path addlinetopoint:cgpointmake(point.x, point.y-3)];
    }
    //y轴(实际长度为200,此处比例缩小一倍使用)
    for (int i=0; i<11; i++) {
        cgfloat y = cgrectgetheight(myframe)-margin-y_every_margin*i;
        cgpoint point = cgpointmake(margin+adddistance,y);
        [path movetopoint:point];
        [path addlinetopoint:cgpointmake(point.x+3, point.y)];
    }
    
    //4.添加索引格文字
    //x轴
    for (int i=0; i<x_names.count+1; i++) {
        cgfloat x = margin + 15 + margin*i;
        uilabel *textlabel = [[uilabel alloc] initwithframe:cgrectmake(x+adddistance, cgrectgetheight(myframe)-margin, margin, 20)];
        if(i < x_names.count){
            textlabel.text = x_names[i];
        }
        else{
            textlabel.text = @"年/月";
        }
        textlabel.font = [uifont systemfontofsize:10];
        textlabel.textalignment = nstextalignmentcenter;
        textlabel.textcolor = [uicolor bluecolor];
        [self addsubview:textlabel];
        
    }
    
    //y轴
    for (int i=0; i<11; i++) {
        cgfloat y = cgrectgetheight(myframe)-margin-y_every_margin*i;
        uilabel *textlabel = [[uilabel alloc] initwithframe:cgrectmake(0, y-5, margin+adddistance, 10)];
        textlabel.text = [nsstring stringwithformat:@"%ld",starting+proportion*10*i];
        textlabel.font = [uifont systemfontofsize:10];
        textlabel.textalignment = nstextalignmentcenter;
        textlabel.textcolor = [uicolor redcolor];
        [self addsubview:textlabel];
    }

    //5.渲染路径
    cashapelayer *shapelayer = [cashapelayer layer];
    shapelayer.path = path.cgpath;
    shapelayer.strokecolor = [uicolor blackcolor].cgcolor;
    shapelayer.fillcolor = [uicolor clearcolor].cgcolor;
    shapelayer.borderwidth = 2.0;
    [self.subviews[0].layer addsublayer:shapelayer];
}

3、实现的方法

/**
 *  画折线图
 *  @param x_names      x轴值的所有值名称
 *  @param targetvalues 所有目标值
 *  @param linetype     直线类型
 *  @param adddistance  y轴的字符串长度的增加距离
 *  @param starting     坐标轴原点的大小数值
 *  @param proportion   y轴上的数值比例差为10的倍数
 */
-(void)drawlinechartviewwithx_value_names:(nsmutablearray *)x_names targetvalues:(nsmutablearray *)targetvalues linetype:(linetype) linetype adddistancevalues:(nsinteger )adddistance  startingvalues:(nsinteger)starting proportionvaluess:(nsinteger)proportion;
/**
 *  画柱状图
 *  @param x_names      x轴值的所有值名称
 *  @param targetvalues 所有目标值
 *  @param adddistance  y轴的字符串长度的增加距离
 *  @param starting     坐标轴原点的大小数值
 *  @param proportion   y轴上的数值比例差为10的倍数
 */
-(void)drawbarchartviewwithx_value_names:(nsmutablearray *)x_names targetvalues:(nsmutablearray *)targetvalues adddistancevalues:(nsinteger )adddistance  startingvalues:(nsinteger)starting proportionvaluess:(nsinteger)proportion;

4、折线图的实现

/**
 *  画折线图
 */
-(void)drawlinechartviewwithx_value_names:(nsmutablearray *)x_names targetvalues:(nsmutablearray *)targetvalues linetype:(linetype) linetype adddistancevalues:(nsinteger )adddistance  startingvalues:(nsinteger)starting proportionvaluess:(nsinteger)proportion{
    
    //1.画坐标轴
    [self drawxyline:x_names adddistancevalues:adddistance startingvalues:starting proportionvaluess:proportion];
    nsmutablearray * targetvalues1 =[[nsmutablearray alloc]init];
    for (int i=0; i<targetvalues.count; i++  ){
        cgfloat coed =[targetvalues[i] integervalue];
        [targetvalues1 addobject:@((coed-starting)/proportion)];

    }
   
    //2.获取目标值点坐标
    nsmutablearray *allpoints = [nsmutablearray array];
    for (int i=0; i<targetvalues1.count; i++) {
        cgfloat doublevalue = 2*[targetvalues1[i] floatvalue]; //目标值放大两倍
        cgfloat x = margin+adddistance + margin*(i+1);
        cgfloat y = cgrectgetheight(myframe)-margin-doublevalue;
        cgpoint point = cgpointmake(x,y);
        uibezierpath *path = [uibezierpath bezierpathwithroundedrect:cgrectmake(point.x-1, point.y-1, 2.5, 2.5) cornerradius:2.5];
        cashapelayer *layer = [cashapelayer layer];
        layer.strokecolor = [uicolor purplecolor].cgcolor;
        layer.fillcolor = [uicolor purplecolor].cgcolor;
        layer.path = path.cgpath;
        [self.subviews[0].layer addsublayer:layer];
        [allpoints addobject:[nsvalue valuewithcgpoint:point]];
    }

    //3.坐标连线
    uibezierpath *path = [uibezierpath bezierpath];
    [path movetopoint:[allpoints[0] cgpointvalue]];
    cgpoint preponit;
    switch (linetype) {
        case linetype_straight: //直线
            for (int i =1; i<allpoints.count; i++) {
                cgpoint point = [allpoints[i] cgpointvalue];
                [path addlinetopoint:point];
            }
            break;
        case linetype_curve:   //曲线
            for (int i =0; i<allpoints.count; i++) {
                if (i==0) {
                    preponit = [allpoints[0] cgpointvalue];
                }else{
                    cgpoint nowpoint = [allpoints[i] cgpointvalue];
                    [path addcurvetopoint:nowpoint controlpoint1:cgpointmake((preponit.x+nowpoint.x)/2, preponit.y) controlpoint2:cgpointmake((preponit.x+nowpoint.x)/2, nowpoint.y)]; //三次曲线
                    preponit = nowpoint;
                }
            }
            break;
    }
    cashapelayer *shapelayer = [cashapelayer layer];
    shapelayer.path = path.cgpath;
    shapelayer.strokecolor = [uicolor greencolor].cgcolor;
    shapelayer.fillcolor = [uicolor clearcolor].cgcolor;
    shapelayer.borderwidth = 2.0;
    [self.subviews[0].layer addsublayer:shapelayer];
    
    //4.添加目标值文字
    for (int i =0; i<allpoints.count; i++) {
        uilabel *label = [[uilabel alloc] init];
        label.textcolor = [uicolor purplecolor];
        label.textalignment = nstextalignmentcenter;
        label.font = [uifont systemfontofsize:10];
        [self.subviews[0] addsubview:label];
        
        if (i==0) {
            cgpoint nowpoint = [allpoints[0] cgpointvalue];
            label.text = [nsstring stringwithformat:@"%.0lf",starting+proportion*(cgrectgetheight(myframe)-nowpoint.y-margin)/2];
            label.frame = cgrectmake(nowpoint.x-margin/2, nowpoint.y-20, margin+adddistance, 20);
            preponit = nowpoint;
        }else{
            cgpoint nowpoint = [allpoints[i] cgpointvalue];
            if (nowpoint.y<preponit.y) {  //文字置于点上方
                label.frame = cgrectmake(nowpoint.x-margin/2, nowpoint.y-20, margin+adddistance, 20);
            }else{ //文字置于点下方
                label.frame = cgrectmake(nowpoint.x-margin/2, nowpoint.y, margin+adddistance, 20);
            }
            
            label.text = [nsstring stringwithformat:@"%.0lf",starting+proportion*(cgrectgetheight(myframe)-nowpoint.y-margin)/2];
       
            preponit = nowpoint;
        }
    }
}

5、柱状图的实现

/**
 *  画柱状图
 */
-(void)drawbarchartviewwithx_value_names:(nsmutablearray *)x_names targetvalues:(nsmutablearray *)targetvalues adddistancevalues:(nsinteger )adddistance  startingvalues:(nsinteger)starting proportionvaluess:(nsinteger)proportion{
    
    //1.画坐标轴
    
    [self drawxyline:x_names adddistancevalues:adddistance startingvalues:starting proportionvaluess:proportion];
    nsmutablearray * targetvalues1 =[[nsmutablearray alloc]init];
    for (int i=0; i<targetvalues.count; i++  ){
        cgfloat coed =[targetvalues[i] integervalue];
        [targetvalues1 addobject:@((coed-starting)/proportion)];
       
    }
    //2.每一个目标值点坐标
    for (int i=0; i<targetvalues1.count; i++) {
        cgfloat doublevalue = 2*[targetvalues1[i] floatvalue]; //目标值放大两倍
        cgfloat x = margin + margin*(i+1)+5;
        cgfloat y = cgrectgetheight(myframe)-margin-doublevalue;
        uibezierpath *path = [uibezierpath bezierpathwithrect:cgrectmake(x-margin/2+adddistance, y, margin-10, doublevalue)];
        cashapelayer *shapelayer = [cashapelayer layer];
        shapelayer.path = path.cgpath;
        shapelayer.strokecolor = [uicolor clearcolor].cgcolor;
        shapelayer.fillcolor = xyqrandomcolor.cgcolor;
        shapelayer.borderwidth = 2.0;
        [self.subviews[0].layer addsublayer:shapelayer];
        
        //3.添加文字
        uilabel *label = [[uilabel alloc] initwithframe:cgrectmake(x-margin/2, y-20, margin-10+adddistance*2, 20)];
        label.text = [nsstring stringwithformat:@"%.0lf",starting+proportion*(cgrectgetheight(myframe)-y-margin)/2];
        label.textcolor = [uicolor purplecolor];
        label.textalignment = nstextalignmentcenter;
        label.font = [uifont systemfontofsize:10];
        [self.subviews[0] addsubview:label];
    }
}

6、父视图view部分代码

- (void)viewdidload {
    [super viewdidload];
    self.view.layer.backgroundcolor=[uicolor whitecolor].cgcolor;
    //1.初始化
    self.bezierview = [beziercurveview initwithframe:cgrectmake(20, 30, screen_w-40, 280)];
    self.bezierview.center = self.view.center;
    [self.view addsubview:self.bezierview];
    //2.折线图
   // [self drawlinechart];
    //3.柱状图
  //  [self drawbasechart];
}

//画折线图
-(void)drawlinechart{
    
    //直线
    //    [self.bezierview drawlinechartviewwithx_value_names:self.x_names targetvalues:self.targets linetype:linetype_straight adddistancevalues:20  startingvalues:120000 proportionvaluess:100];

   // [self.bezierview drawlinechartviewwithx_value_names:self.x_names targetvalues:self.targets linetype:linetype_curve adddistancevalues:10  startingvalues:50000 proportionvaluess:100];
   // [self.bezierview drawlinechartviewwithx_value_names:self.x_names targetvalues:self.targets linetype:linetype_curve adddistancevalues:20  startingvalues:120000 proportionvaluess:100];
}

7、iponexr演示结果图片

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网