iOS 折线图、柱状图的简单实现
程序员文章站
2023-08-26 18:07:19
首先我得感谢某位博主,非常抱歉,因为之前直接下载博主提供这篇文章的demo,然后去研究了,没记住博主的名字。再次非常感谢。 而这个dome我又修改了一些,完善了一些不美观的bug,当然还有,后面会陆续更新。 1 、一开始需要给坐标轴初始一个画布 2、然后画坐标轴,包括x、y轴的直线、箭头、字符串的索 ......
首先我得感谢某位博主,非常抱歉,因为之前直接下载博主提供这篇文章的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演示结果图片
下一篇: 前任3再见前任一个平凡真实的结局