大数据(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,希望能给大家带来帮助,也希望能看到大神的更精彩的分享。