iOS数据统计(柱状图、折线图、扇形图)

大数据(big data),指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

大数据技术的战略意义不在于掌握庞大的数据信息,而在于对这些含有意义的数据进行专业化处理。换而言之,如果把大数据比作一种产业,那么这种产业实现盈利的关键,在于提高对数据的“加工能力”,通过“加工”实现数据的“增值”。

前言

今年大数据行业火爆异常,大数据的实用点之一在于数据的统计和加工实现数据的“增值”,方便人们从大量的数据统计中得出结论。

对于一个iOS开发程序猿来说不是专门搞大数据开发的,似乎没有多大关系,但后续iOS开发中,各类APP中必然会加入统计表格的形式展示数据,相对于传统的列表形式+各类查询显示,表格形式直观、简洁、通俗易懂,分析更透彻,必然会成为抢手货。

本文介绍一下简易的柱状图、折线图、扇形图三种统计图的制作,希望能帮助到大家

坐标系

利用CAShapeLayer和UIBezierPath绘制坐标系,坐标系中需要绘制的部分如下图所示:

坐标系

需要绘制的部分有原点、x坐标轴、y坐标轴、坐标轴末尾的箭头和坐标轴上的标度。需要计算位置和长度,需要根据所在页面的大小计算坐标系的位置和大小。

这里给出代码如下:

CAShapeLayer *layer = [CAShapeLayer layer];

UIBezierPath *path = [UIBezierPath bezierPath];

//坐标轴原点

CGPointrPoint = CGPointMake(1.3*margin,self.zzHeight-margin);

//画y轴

[path moveToPoint:rPoint];

[path addLineToPoint:CGPointMake(1.3*margin, margin)];

//画y轴的箭头

[path moveToPoint:CGPointMake(1.3*margin, margin)];

[path addLineToPoint:CGPointMake(1.3*margin-5, margin+5)];

[path moveToPoint:CGPointMake(1.3*margin, margin)];

[path addLineToPoint:CGPointMake(1.3*margin+5, margin+5)];

//画x轴

[path moveToPoint:rPoint];

[path addLineToPoint:CGPointMake(self.zzWidth-0.8*margin,self.zzHeight-margin)];

//画x轴的箭头

[path moveToPoint:CGPointMake(self.zzWidth-0.8*margin,self.zzHeight-margin)];

[path addLineToPoint:CGPointMake(self.zzWidth-0.8*margin-5,self.zzHeight-margin-5)];

[path moveToPoint:CGPointMake(self.zzWidth-0.8*margin,self.zzHeight-margin)];

[path addLineToPoint:CGPointMake(self.zzWidth-0.8*margin-5,self.zzHeight-margin+5)];

//画x轴上的标度

for(int i=0; i < x_itemArr.count; i++) {

[path moveToPoint:CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1),self.zzHeight-margin)];

[path addLineToPoint:CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1),self.zzHeight-margin-3)];

}

//画y轴上的标度

for(int i=0; i<10; i++) {

[path moveToPoint:CGPointMake(1.3*margin, margin+(self.zzHeight-2*margin)/11*(i+1))];

[path addLineToPoint:CGPointMake(1.3*margin+3, margin+(self.zzHeight-2*margin)/11*(i+1))];

}

layer.path= path.CGPath;

layer.fillColor= [UIColor clearColor].CGColor;

layer.strokeColor= [UIColor blackColor].CGColor;

layer.lineWidth=2.0;

[self.layer addSublayer:layer];

//给y轴加标注

for(int i=0; i<11; i++) {

CGFloat yLHeight = (self.zzHeight-2*margin)/11<=20? (self.zzHeight-2*margin)/11:20;

CGFloat yLWidth = yLHeight*2>=25?25: yLHeight*2;

CGFloat size = (self.zzHeight-2*margin)/11<=20?7:12;

UILabel*lab = [[UILabel alloc] initWithFrame:CGRectMake(1.3*margin-yLWidth-5, margin+(self.zzHeight-2*margin)/11*(10-i+0.5), yLWidth, yLHeight)];

lab.text= [NSString stringWithFormat:@"%d",10*i];

lab.textColor= [UIColor blackColor];

lab.font= [UIFont boldSystemFontOfSize:size];

lab.textAlignment= NSTextAlignmentCenter;

[self addSubview:lab];

}

柱状图

在绘制坐标系的基础上,绘制柱状图的原理非常简单,根据x轴的坐标,计算每条柱的高度。

这里需要注意:

提供的数据需要转化为自己设定的y轴的刻度单位计算出的高度。另外,柱状图需要占用x轴的宽度,所以柱子的位置需要好好考虑一下放在x轴的什么位置。

代码如下:

//画柱状图

for(int i=0; i < x_itemArr.count; i++) {

UIBezierPath*path = [UIBezierPath bezierPathWithRect:CGRectMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+0.7),self.zzHeight-margin-(self.zzHeight-2*margin)/11*[y_itemArr[i] floatValue]/10,0.6*((self.zzWidth-2*margin)/(x_itemArr.count+1)),(self.zzHeight-2*margin)/11*[y_itemArr[i] floatValue]/10-1)];

CAShapeLayer*layer = [CAShapeLayer layer];

layer.path= path.CGPath;

layer.fillColor=zzRandomColor.CGColor;

layer.strokeColor= [UIColor clearColor].CGColor;

[self.layer addSublayer:layer];

}

//给x轴加标注

for(int i=0; i < x_itemArr.count; i++) {

CGFloat xLWidth = ((self.zzWidth-2*margin)/(x_itemArr.count+1)) <=25? ((self.zzWidth-2*margin)/(x_itemArr.count+1)) :25;

UILabel*lab = [[UILabel alloc]initWithFrame:CGRectMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1)-xLWidth/2,self.zzHeight-margin, xLWidth,20)];

lab.text= x_itemArr[i];

lab.textColor= [UIColorblackColor];

lab.adjustsFontSizeToFitWidth=YES;

lab.textAlignment=NSTextAlignmentCenter;

[self addSubview:lab];

}

效果如下:

柱状图

折线图

在坐标系的基础上,计算绘制对应y轴上的点,然后从第一个点开始,依次连接到最后一个点,可以直线连接,或者用贝塞尔曲线绘制,具体看实际情况实现。

代码如下:

//开始点

CGPointstartPoint = CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1),self.zzHeight-margin-(self.zzHeight-2*margin)/11*[y_itemArr[0] floatValue]/10);

//结束点

CGPoint endPoint;

for(int i=0; i < x_itemArr.count; i++) {

endPoint = CGPointMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1),self.zzHeight-margin-(self.zzHeight-2*margin)/11*[y_itemArr[i] floatValue]/10);

UIBezierPath *path = [UIBezierPath bezierPath];

[path moveToPoint:startPoint];

[path addArcWithCenter:endPoint radius:1.5startAngle:0endAngle:2*M_PI clockwise:YES];

[path addLineToPoint:endPoint];

//绘制连线

CAShapeLayer *layer = [CAShapeLayer layer];

layer.path= path.CGPath;

layer.strokeColor= [UIColorredColor].CGColor;

layer.lineWidth=1.0;

[self.layer addSublayer:layer];

//绘制点

CAShapeLayer *layer1 = [CAShapeLayer layer];

layer1.frame= CGRectMake(endPoint.x-2, endPoint.y-2,4,4);

layer1.backgroundColor= [UIColorblackColor].CGColor;

[self.layer addSublayer:layer1];

//绘制虚线

CAShapeLayer *shapeLayer = [CAShapeLayer layer];

[shapeLayer setStrokeColor:[UIColorblackColor].CGColor];

[shapeLayer setLineWidth:1];

[shapeLayer setLineJoin:kCALineJoinRound];

//设置虚线的线宽及间距

[shapeLayer setLineDashPattern:[NSArrayarrayWithObjects:[NSNumber numberWithInt:2], [NSNumber numberWithInt:3],nil]];

//创建虚线绘制路径

CGMutablePathRef path = CGPathCreateMutable();

//设置y轴方向的虚线

CGPathMoveToPoint(path,NULL, point.x, point.y);

CGPathAddLineToPoint(path,NULL, point.x,self.zzHeight-margin);

//设置x轴方向的虚线

CGPathMoveToPoint(path,NULL, point.x, point.y);

CGPathAddLineToPoint(path,NULL,1.3*margin, point.y);

//设置虚线绘制路径

[shapeLayer setPath:path];

CGPathRelease(path);

[self.layer addSublayer:shapeLayer];

startPoint = endPoint;

}

//给x轴加标注

for(int i=0; i < x_itemArr.count; i++) {

CGFloat xLWidth = ((self.zzWidth-2*margin)/(x_itemArr.count+1)) <= 25 ? ((self.zzWidth-2*margin)/(x_itemArr.count+1)) : 25;

UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(1.3*margin+(self.zzWidth-2*margin)/(x_itemArr.count+1)*(i+1)-xLWidth/2, self.zzHeight-margin, xLWidth, 20)];

lab.text = x_itemArr[i];

lab.textColor = [UIColor blackColor];

lab.adjustsFontSizeToFitWidth = YES;

lab.textAlignment = NSTextAlignmentCenter;

[self addSubview:lab];

}

效果图如下:

折线图

扇形图

扇形图制作需要首先计算每一条数据占数据总和的百分比,然后以页面中心点为中心,指定半径,开始画扇形,每条数据对应一个扇形,起点半径每次都不一样,知道最后一条数据画完,可以正好得到一个整圆。

代码如下:

CGPoint yPoint = CGPointMake(self.zzWidth/2,self.zzHeight/2);

CGFloat startAngle =0;

CGFloat endAngle;

floatr =self.zzHeight/3;

//求和

floatsum=0;

for(NSString*str in y_itemArr) {

sum += [str floatValue];

}

for(inti=0; i  < x_itemArr.count; i++) {

endAngle = startAngle + zhanbi*2*M_PI;

CAShapeLayer *layer = [CAShapeLayer layer];

UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:yPoint radius:r startAngle:startAngle endAngle:endAngle clockwise:YES];

[path addLineToPoint:yPoint];

[path closePath];

CGFloat bLWidth =self.zzHeight/6+5>=45?40:self.zzHeight/6;

CGFloat size =self.zzHeight/6+5>=45?9:5;

CGFloat lab_x = yPoint.x+ (r + bLWidth/2) * cos((startAngle + (endAngle - startAngle)/2)) - bLWidth/2;

CGFloat lab_y = yPoint.y+ (r + bLWidth*3/8) * sin((startAngle + (endAngle - startAngle)/2)) - bLWidth*3/8;

UILabel*lab = [[UILabelalloc] initWithFrame:CGRectMake(lab_x, lab_y, bLWidth, bLWidth*3/4)];

lab.text=[NSStringstringWithFormat:@"%@\n%.2f%@",x_itemArr[i],zhanbi*100,@"%"];

lab.textColor= [UIColor blackColor];

lab.numberOfLines=0;

lab.font= [UIFont boldSystemFontOfSize:size];

lab.textAlignment= NSTextAlignmentCenter;

[self addSubview:lab];

layer.path= path.CGPath;

layer.fillColor= zzRandomColor.CGColor;

layer.strokeColor= [UIColor clearColor].CGColor;

[self.layer addSublayer:layer];

startAngle = endAngle;

}

效果图如下:

扇形图

尾声

简易的三种画法,仅用于展示数据,封装类和Demo已经上传到了GitHub上,地址:https://github.com/fuzheng0301/DrawChart ,感谢star,希望能给大家带来帮助,也希望能看到大神的更精彩的分享。

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

推荐阅读更多精彩内容