iOS 柱状图的定制

最近因项目需求,要使用柱状图,第三方的东西固然很好,但是我还是想要写一个自己的柱状图,因为更加符合我们项目的需求,日后维护起来也会方便许多。

写了一个自定义视图,可以自定义众多属性,关键是使用起来方便,最少四行就可以了。

废话不多说,上代码:

WQLChartView.h文件:

 1 typedef NS_ENUM(NSInteger ,ChartViewType) {
 2     ChartViewTypeColumn,
 3     ChartViewTypePoint
 4 };
 5
 6 @interface WQLChartView : UIView
 7 /**
 8  *  图表的类型
 9  */
10 @property (nonatomic,assign) ChartViewType type;
11 /**
12  *  单列的宽度
13  */
14 @property (nonatomic,assign) CGFloat singleRowWidth;
15 /**
16  *  每个柱子之间的间距
17  */
18 @property (nonatomic,assign) CGFloat singleChartSpace;
19 /**
20  *  x的值 数组
21  */
22 @property (nonatomic,strong) NSArray *xValueArray;
23 /**
24  *  y的值 数组
25  */
26 @property (nonatomic,strong) NSArray *yValueArray;
27 /**
28  *  x轴的右侧标题(比如:时间)
29  */
30 @property (nonatomic,copy) NSString *xAxleTitle;
31 /**
32  *  y轴的顶部标题 (比如:万件)
33  */
34 @property (nonatomic,copy) NSString *yAxleTitle;
35 /**
36  *  y轴上有几个点
37  */
38 @property (nonatomic,assign) NSInteger yAxlePointNumber;
39 /**
40  *  y轴的坐标点 数组
41  */
42 @property (nonatomic,strong) NSArray *yPointArray;
43 /**
44  *  柱子的颜色
45  */
46 @property (nonatomic,strong) UIColor *columnColor;
47 /**
48  *  是否显示线条
49  */
50 @property (nonatomic,assign) BOOL showLine;
51 /**
52  *  连线的颜色
53  */
54 @property (nonatomic,strong) UIColor *lineColor;
55 /**
56  *  连线的宽度(粗细)
57  */
58 @property (nonatomic,assign) CGFloat lineWidth;
59 /**
60  *  点的颜色(只有是point类型才有效)
61  */
62 @property (nonatomic,strong) UIColor *pointColor;
63 /**
64  *  点的宽度(只有point类型才有效)
65  */
66 @property (nonatomic,assign) CGFloat pointWidth;
67 /**
68  *  连接是否使用平滑的曲线
69  */
70 @property (nonatomic,assign) BOOL lineIsCurve;
71 /**
72  *  是否隐藏数值 默认不隐藏
73  */
74 @property (nonatomic,assign) BOOL isHideNumber;
75 /**
76  *  数值的颜色
77  */
78 @property (nonatomic,strong) UIColor *colorOfNumber;
79 /**
80  *  数值的字号
81  */
82 @property (nonatomic,assign) NSInteger fontSizeOfNumber;
83
84 //在superView上展示视图 必须调用 参数配置完毕后调用
85 - (void)showChartInView:(UIView*)superView;
86
87 //更新视图
88 - (void)updateView;

WQLChartView.m文件 核心代码:

  1 #pragma  mark 添加柱状图
  2 - (void)loadColumnShapeWithSingleWidth:(CGFloat)singleW withSpace:(CGFloat)singleSpace
  3 {
  4
  5     CGFloat viewHeight = self.bounds.size.height;
  6     //如果改动了 则把之前的显示部分移除掉
  7     if (isChange) {
  8         [self deletePointLayer];
  9     }
 10
 11     //如果之前 添加了 则把之前的删了
 12     if (columnShapeLayerArray.count > 0) {
 13         for (CAShapeLayer *layer in columnShapeLayerArray) {
 14             [layer removeFromSuperlayer];
 15         }
 16     }
 17
 18     //把之前添加的线 移除掉
 19     if (lineArray.count > 0) {
 20         for (CAShapeLayer *lineLayer in lineArray) {
 21             [lineLayer removeFromSuperlayer];
 22         }
 23     }
 24
 25     columnShapeLayerArray = [NSMutableArray array];
 26     lineArray = [NSMutableArray array];
 27
 28     UIBezierPath *column = [UIBezierPath bezierPath];
 29
 30     CGFloat xPosition = 0;
 31     if (!topPointYArray) {
 32         topPointYArray = [NSMutableArray array];
 33     }else{
 34         [topPointYArray removeAllObjects];
 35     }
 36
 37     for (int i = 0; i<xCount; i++) {
 38         CAShapeLayer *columnLayer = [CAShapeLayer layer];
 39         //当前的y值
 40         NSString *value = _yValueArray[i];
 41         CGFloat yValue = [value floatValue];
 42         //y值 占坐标最大值的比率
 43         CGFloat rate = yValue/yMax;
 44         //单个柱子的高度
 45         CGFloat singleHeight = (viewHeight-titleWidth-yArrowHeight)*rate;
 46
 47         NSString *topPointY = [NSString stringWithFormat:@"%f",viewHeight-titleWidth-singleHeight];
 48         [topPointYArray addObject:topPointY];
 49
 50         //x轴 为柱子左下侧的点 y为坐标轴
 51         [column moveToPoint:CGPointMake(xPosition+singleSpace+titleWidth, viewHeight-titleWidth)];
 52         //柱子的左侧垂直线
 53         [column addLineToPoint:CGPointMake(xPosition+singleSpace+titleWidth, viewHeight-titleWidth-singleHeight)];
 54         //柱子的顶部水平线
 55         [column addLineToPoint:CGPointMake(xPosition+singleSpace+titleWidth+singleW, viewHeight-titleWidth-singleHeight)];
 56         //柱子的右侧垂直线
 57         [column addLineToPoint:CGPointMake(xPosition+singleSpace+titleWidth+singleW, viewHeight-titleWidth)];
 58
 59         if (self.showLine) {
 60
 61             UIBezierPath *line = [UIBezierPath bezierPath];
 62
 63             CAShapeLayer *lineLayer = [CAShapeLayer layer];
 64
 65             if (i>0) {
 66                 //上一个点的y值
 67                 NSString *lastValue = _yValueArray[i-1];
 68                 CGFloat lastYValue = [lastValue floatValue];
 69                 CGFloat lastRate = lastYValue/yMax;
 70                 //取到上一个点的高度
 71                 CGFloat lastSingleHeight = (viewHeight-titleWidth-yArrowHeight)*lastRate;
 72
 73                 //移到柱子的顶部中点
 74                 [line moveToPoint:CGPointMake(xPosition+singleSpace+titleWidth+singleW/2, viewHeight-titleWidth-singleHeight)];
 75                 //向上一个点 添加连线
 76                 if (self.lineIsCurve) {
 77                     //曲线连接
 78                     //上一个点的x坐标
 79                     CGFloat lastPointX = xPosition+singleSpace+titleWidth+singleW/2-(singleW+singleSpace);
 80                     //上一个点的y坐标
 81                     CGFloat lastPointY = viewHeight - titleWidth-lastSingleHeight;
 82                     //该柱子顶部中点的x坐标
 83                     CGFloat pointX = xPosition+singleSpace+titleWidth+singleW/2;
 84                     //该柱子顶部中点的y坐标
 85                     CGFloat pointY = viewHeight-titleWidth-singleHeight;
 86                     //添加曲线 两个控制点 x为两个点的中间点 y为首末点的y坐标 为了实现平滑连接
 87                     [line addCurveToPoint:CGPointMake(lastPointX, lastPointY) controlPoint1:CGPointMake((pointX+lastPointX)/2, pointY) controlPoint2:CGPointMake((pointX+lastPointX)/2, lastPointY)];
 88                 }else{
 89                     //直线连接
 90                     [line addLineToPoint:CGPointMake(xPosition+singleSpace+titleWidth+singleW/2-(singleW+singleSpace), viewHeight-titleWidth-lastSingleHeight)];
 91                 }
 92
 93             }
 94             lineLayer.path = line.CGPath;
 95             //线条宽度
 96             lineLayer.lineWidth = self.lineWidth>0?self.lineWidth:2;
 97             if (!self.lineColor) {
 98                 self.lineColor = [UIColor redColor];
 99             }
100             //线条颜色
101             lineLayer.strokeColor = self.lineColor.CGColor;
102             lineLayer.fillColor = [UIColor clearColor].CGColor;
103             [lineArray addObject:lineLayer];
104
105         }
106
107         columnLayer.path = column.CGPath;
108         if (!self.columnColor) {
109             self.columnColor = [UIColor orangeColor];
110         }
111
112         columnLayer.fillColor = CGColorCreateCopyWithAlpha(self.columnColor.CGColor, 1.0);
113         columnLayer.strokeStart = 0;
114         columnLayer.strokeEnd = 1.0;
115         [columnShapeLayerArray addObject:columnLayer];
116
117         [self.layer addSublayer:columnLayer];
118
119         for (CAShapeLayer *lineLayer in lineArray) {
120             [self.layer addSublayer:lineLayer];
121         }
122
123         xPosition += (singleW+singleSpace);
124
125     }
126 }
127 #pragma  mark  添加 点视图
128 - (void)loadPointInChartView
129 {
130     if (isChange) {
131         [self deleteColumnLayer];
132     }
133
134     UIBezierPath *circle = [UIBezierPath bezierPath];
135
136     CGFloat viewHeight = self.bounds.size.height;
137
138     //如果之前 添加了 则把之前的删了
139     if (pointShapeLayerArray.count > 0) {
140         for (CAShapeLayer *layer in pointShapeLayerArray) {
141             [layer removeFromSuperlayer];
142         }
143     }
144
145     //把之前添加的线条删除了
146     if (lineArray.count > 0) {
147         for (CAShapeLayer *lineLayer in lineArray) {
148             [lineLayer removeFromSuperlayer];
149         }
150     }
151
152     pointShapeLayerArray = [NSMutableArray array];
153     lineArray = [NSMutableArray array];
154
155     if (!topPointYArray) {
156         topPointYArray = [NSMutableArray array];
157     }else{
158         [topPointYArray removeAllObjects];
159     }
160     //顶部中点连线
161     NSInteger count = topCenterPointXArray.count;
162     if (count >0) {
163
164         for (int i = 0; i<topCenterPointXArray.count; i++) {
165
166             CAShapeLayer *circleLayer = [CAShapeLayer layer];
167
168             NSString *topPoint = topCenterPointXArray[i];
169             CGFloat pointX = [topPoint floatValue];
170             //y值
171             CGFloat yValues = [self.yValueArray[i] floatValue];
172             //y坐标又是不一样了 y值越大,柱子越高,坐标其实是越小
173             CGFloat pointY = (1-(yValues/yMax))*(viewHeight-yArrowHeight-titleWidth)+yArrowHeight;
174
175             [topPointYArray addObject:[NSString stringWithFormat:@"%f",pointY]];
176
177             [circle moveToPoint:CGPointMake(pointX, pointY)];
178
179             CGFloat radius = self.pointWidth >0 ?self.pointWidth:5.0;
180             //标示点 为圆
181             [circle  addArcWithCenter:CGPointMake(pointX, pointY) radius:radius startAngle:0 endAngle:M_PI*2 clockwise:YES];
182             circleLayer.path = circle.CGPath;
183             if (!self.pointColor) {
184                 self.pointColor = [UIColor orangeColor];
185             }
186             //圆点的填充色
187             circleLayer.fillColor = CGColorCreateCopyWithAlpha(self.pointColor.CGColor, 1.0);
188             circleLayer.strokeStart = 0;
189             circleLayer.strokeEnd = 1.0;
190             circleLayer.lineWidth = 1;
191             [pointShapeLayerArray addObject:circleLayer];
192
193             if (self.showLine) {
194
195                 UIBezierPath *line = [UIBezierPath bezierPath];
196
197                 CAShapeLayer *lineLayer = [CAShapeLayer layer];
198
199                 if (i>0) {
200                     NSString *lastXValue = topCenterPointXArray[i-1];
201                     CGFloat lastPointX = [lastXValue floatValue];
202
203                     NSString *lastValue = _yValueArray[i-1];
204                     CGFloat lastYValue = [lastValue floatValue];
205                     //y坐标又是不一样了 y值越大,柱子越高,坐标其实是越小
206                     CGFloat lastPointY = (1-(lastYValue/yMax))*(viewHeight-yArrowHeight-titleWidth)+yArrowHeight;
207
208                     //移到中点
209                     [line moveToPoint:CGPointMake(pointX,pointY)];
210
211                     if (self.lineIsCurve) {
212                         //曲线连接 两个控制点 x为两个点的中间点 y为首末点的y坐标 为了实现平滑连接
213                         [line addCurveToPoint:CGPointMake(lastPointX, lastPointY) controlPoint1:CGPointMake((pointX+lastPointX)/2, pointY) controlPoint2:CGPointMake((pointX+lastPointX)/2, lastPointY)];
214                     }else{
215                         //向上一个点 添加连线
216                         [line addLineToPoint:CGPointMake(lastPointX,lastPointY)];
217                     }
218
219                 }
220                 lineLayer.path = line.CGPath;
221                 lineLayer.lineWidth = self.lineWidth>0?self.lineWidth:2;
222                 if (!self.lineColor) {
223                     self.lineColor = [UIColor blackColor];
224                 }
225                 lineLayer.strokeColor = self.lineColor.CGColor;
226                 lineLayer.fillColor = [UIColor clearColor].CGColor;
227                 [lineArray addObject:lineLayer];
228
229             }
230
231         }
232     }
233
234     for (CAShapeLayer *layer  in pointShapeLayerArray) {
235         [self.layer addSublayer:layer];
236     }
237
238     for (CAShapeLayer *lineLayer in lineArray) {
239         [self.layer addSublayer:lineLayer];
240     }
241
242 }

总计八百多行,我就不一一贴出了。上述两个方法是核心的添加方法。

接下来看一下该怎么使用:

 1 - (void)loadChartView
 2 {
 3     chartView = [[WQLChartView alloc]initWithFrame:CGRectMake(10, 100,chartWidth, chartHeight)];
 4     chartView.singleRowWidth = 50;//可注释掉
 5     chartView.columnColor = [UIColor lightGrayColor];//可注释掉
 6     chartView.pointColor = [UIColor orangeColor];//可注释掉
 7     chartView.xAxleTitle = @"日";//可注释掉
 8     chartView.yAxleTitle = @"件";//可注释掉
 9     chartView.type = ChartViewTypeColumn;//可注释掉
10     chartView.showLine = YES;//可注释掉
11     chartView.lineColor = [UIColor blueColor];//可注释掉
12     chartView.lineIsCurve = YES;//可注释掉
13     chartView.colorOfNumber = [UIColor redColor];//可注释掉
14     chartView.yPointArray = @[@"20",@"40",@"60",@"80",@"100"];//可注释掉
15     chartView.xValueArray = xValuesArray;
16     chartView.yValueArray = yValuesArray;
17     [chartView showChartInView:self.view];
18
19 }

最简单的就是全部非必要属性使用默认的,仅需4行即可加载柱状图。

回到要点上,功能才是王道:

添加柱子:

切换类型:

由头文件的属性可知,以下属性都可以修改:

图表的类型:分为柱状的和点状的
单列的宽度:柱状图时有效,默认25
每个柱子之间的间距:柱状图时有效
x的值数组:必须赋值的属性,为X轴上的点
y的值数组:必须赋值的属性,为对应的x的y值
x轴的右侧标题:可设置属性,为x轴的单位
y轴的顶部标题:可设置属性,为y轴的单位
y轴上的点的个数:可设置属性,默认为5个点,即y轴被分为5等份
y轴的坐标点数组:y轴上的刻度点
柱子的颜色:可设置属性,默认为橘黄色
是否显示线条:可设置属性,默认不显示线条
连线的颜色:可设置属性,默认为红色
连线的宽度:可设置属性,默认为2
点的颜色:点状图时有效,默认橙色
点的宽度:点状图时有效,标示的点的半径
是否使用平滑的曲线:连线的形状,默认使用直线连接
是否隐藏数值:不显示数字,默认为NO,不隐藏
数值的颜色:显示的数值的文本颜色,默认为黑色
数值的字号:数值的文本字号,默认为14号

需要额外提一点的是:用户的柱子宽度一定,当数量比较多时,原来的给定的尺寸不足以显示的时候,我将柱子的宽度缩小了以实现刚好填充的效果。

如有不足之处还请各位园友指导~一起学习一起进步!

完整的代码在这里:ChartView 1

时间: 2024-10-18 18:08:49

iOS 柱状图的定制的相关文章

RBPlayer 教程:iOS 高度可定制的播放器

RBPlayer基于AVPlayer的高度可定制的播放器,要求iOS 7.0及以上版本. 特点: 完全可自定义UI 没有层级及位置大小等限制 支持全屏播放,支持忽略竖屏锁定 更多RBPlayer 教程:iOS 高度可定制的播放器,请查阅勤快学http://qkxue.net.

iOS 键盘类型定制归纳

一.键盘风格 支持8种风格键盘. typedef enum { UIKeyboardTypeDefault, // 默认键盘:支持所有字符 UIKeyboardTypeASCIICapable, // 支持ASCII的默认键盘 UIKeyboardTypeNumbersAndPunctuation, // 标准电话键盘,支持+*#等符号 UIKeyboardTypeURL, // URL键盘,有.com按钮:只支持URL字符 UIKeyboardTypeNumberPad, //数字键盘 UIK

iOS柱状图的绘制

前段时间公司要求做一个统计,用swift3.0写的,因此整理了一下demo,直接上图 代码下载地址:https://github.com/minyahui/MYHChartView

iOS statusBar 状态栏定制

1 UIWindow * statusWindow = [[UIWindow alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame]; 2 [statusWindow setWindowLevel:UIWindowLevelStatusBar + 1]; 3 [statusWindow setBackgroundColor:[UIColor clearColor]]; 4 5 UILabel * statusL

Xamarin iOS教程之添加和定制视图

Xamarin iOS教程之添加和定制视图 Xamarin iOS用户界面——视图 在iPhone或者iPad中,用户看到的摸到的都是视图.视图是用户界面的重要组成元素.例如,想要让用户实现文本输入时,需要使用输入文本的视图:想要让用户显示图像时,需要使用显示图像的视图.本章将为开发者详细讲解如何构建视图. Xamarin iOS视图 在应用程序开发中,最常见的视图如表2-1所示. 表2-1  常用视图   Xamarin iOS添加和定制视图 本节将主要讲解视图的两种添加方式:一种是使用Int

iOS 视图控制器转场详解

前言的前言 唐巧前辈在微信公众号「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各项指标有了大幅度的增长,多谢唐巧前辈的推荐.有些人问我相关的问题,好吧,目前为止就几个,由于没有评论系统,实在不方便交流,但我也没把博客好好整理,一直都在简书上写博客,大家有问题请移步我的简书本文章的页面.关于交流,我想说这么几点: 1.问问题就好,不要加上大神大牛之类的称呼,与本文有关的问题我尽量回答:不负责解析转场动画,看心情回答. 2.去我的简书下留言是最有效的交流方式,要加我好友就

[IOS/翻译]Cocoa Touch Layer

本文是本人自己辛苦翻译的,请转载的朋友注明,翻译于Z.MJun的CSDN的博客 http://blog.csdn.net/Zheng_Paul,感谢! 翻译于2015年10月6日 Cocoa Touch Layer Cocoa Touch层包含了关键的库来构建IOS应用.这些库定义了应用的表现.他们提供应用的基本空间和提供关键技术,如多任务,以接触为基础的输入,消息推送,和许多高级的系统服务.当你设计你的应用时候,你需要优先研究他们. 高级别的特性 接下来的章节描述一些关键技术 App Exte

UIView你知道多少

转载自:http://www.cnblogs.com/likwo/archive/2011/06/18/2084192.html 曾经有人这么说过,在iphone里你看到的,摸到的,都是UIView,所以UIView在iphone开发里具有非常重要的作用.那么UIView我们到底知道多少呢.请看看下面的问题, 如果这些你都知道,那么本文章的内容就请绕道,如果你还不太清楚,我想看了下面的内容,你就明白了. 1.bounds和frame分别表示什么? 2.ContentMode里UIViewCont

关于UIView(转)

曾经有人这么说过,在iphone里你看到的,摸到的,都是UIView,所以UIView在iphone开发里具有非常重要的作用.那么UIView我们到底知道多少呢.请看看下面的问题, 如果这些你都知道,那么本文章的内容就请绕道,如果你还不太清楚,我想看了下面的内容,你就明白了. 1.bounds和frame分别表示什么? 2.ContentMode里UIViewContentModeScaleToFill代表什么? 3.contentStretch 里的指定UIView里缩放区域是如何计算的? 4