当前位置:首页 > 操作系统 > Ios

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;
8384//在superView上展示视图 必须调用 参数配置完毕后调用85 - (void)showChartInView:(UIView*)superView;
8687//更新视图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//如果改动了 则把之前的显示部分移除掉  7if (isChange) {
  8        [self deletePointLayer];
  9    }
 10 11//如果之前 添加了 则把之前的删了 12if (columnShapeLayerArray.count > 0) {
 13for (CAShapeLayer *layer in columnShapeLayerArray) {
 14            [layer removeFromSuperlayer];
 15        }
 16    }
 17 18//把之前添加的线 移除掉 19if (lineArray.count > 0) {
 20for (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;
 31if (!topPointYArray) {
 32         topPointYArray = [NSMutableArray array];
 33     }else{
 34        [topPointYArray removeAllObjects];
 35    }
 36 37for (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 59if (self.showLine) {
 60 61             UIBezierPath *line = [UIBezierPath bezierPath];
 62 63             CAShapeLayer *lineLayer = [CAShapeLayer layer];
 64 65if (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//向上一个点 添加连线 76if (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;
 97if (!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];
104105        }
106107         columnLayer.path = column.CGPath;
108if (!self.columnColor) {
109             self.columnColor = [UIColor orangeColor];
110        }
111112         columnLayer.fillColor = CGColorCreateCopyWithAlpha(self.columnColor.CGColor, 1.0);
113         columnLayer.strokeStart = 0;
114         columnLayer.strokeEnd = 1.0;
115        [columnShapeLayerArray addObject:columnLayer];
116117        [self.layer addSublayer:columnLayer];
118119for (CAShapeLayer *lineLayer in lineArray) {
120            [self.layer addSublayer:lineLayer];
121        }
122123         xPosition += (singleW+singleSpace);
124125    }
126}
127#pragma  mark  添加 点视图
128 - (void)loadPointInChartView
129{
130if (isChange) {
131        [self deleteColumnLayer];
132    }
133134     UIBezierPath *circle = [UIBezierPath bezierPath];
135136     CGFloat viewHeight = self.bounds.size.height;
137138//如果之前 添加了 则把之前的删了139if (pointShapeLayerArray.count > 0) {
140for (CAShapeLayer *layer in pointShapeLayerArray) {
141            [layer removeFromSuperlayer];
142        }
143    }
144145//把之前添加的线条删除了146if (lineArray.count > 0) {
147for (CAShapeLayer *lineLayer in lineArray) {
148            [lineLayer removeFromSuperlayer];
149        }
150    }
151152     pointShapeLayerArray = [NSMutableArray array];
153     lineArray = [NSMutableArray array];
154155if (!topPointYArray) {
156         topPointYArray = [NSMutableArray array];
157     }else{
158        [topPointYArray removeAllObjects];
159    }
160//顶部中点连线161     NSInteger count = topCenterPointXArray.count;
162if (count >0) {
163164for (int i = 0; i<topCenterPointXArray.count; i++) {
165166             CAShapeLayer *circleLayer = [CAShapeLayer layer];
167168             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;
174175             [topPointYArray addObject:[NSString stringWithFormat:@"%f",pointY]];
176177            [circle moveToPoint:CGPointMake(pointX, pointY)];
178179             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;
183if (!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];
192193if (self.showLine) {
194195                 UIBezierPath *line = [UIBezierPath bezierPath];
196197                 CAShapeLayer *lineLayer = [CAShapeLayer layer];
198199if (i>0) {
200                     NSString *lastXValue = topCenterPointXArray[i-1];
201                     CGFloat lastPointX = [lastXValue floatValue];
202203                     NSString *lastValue = _yValueArray[i-1];
204                     CGFloat lastYValue = [lastValue floatValue];
205//y坐标又是不一样了 y值越大,柱子越高,坐标其实是越小206                     CGFloat lastPointY = (1-(lastYValue/yMax))*(viewHeight-yArrowHeight-titleWidth)+yArrowHeight;
207208//移到中点209                    [line moveToPoint:CGPointMake(pointX,pointY)];
210211if (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                    }
218219                }
220                 lineLayer.path = line.CGPath;
221                 lineLayer.lineWidth = self.lineWidth>0?self.lineWidth:2;
222if (!self.lineColor) {
223                     self.lineColor = [UIColor blackColor];
224                }
225                 lineLayer.strokeColor = self.lineColor.CGColor;
226                 lineLayer.fillColor = [UIColor clearColor].CGColor;
227                [lineArray addObject:lineLayer];
228229            }
230231        }
232    }
233234for (CAShapeLayer *layer  in pointShapeLayerArray) {
235        [self.layer addSublayer:layer];
236    }
237238for (CAShapeLayer *lineLayer in lineArray) {
239        [self.layer addSublayer:lineLayer];
240    }
241242 }

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

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

             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];
1819 }

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

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

添加柱子:

技术分享

 

切换类型:

技术分享

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

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

 

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

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

完整的代码在这里:                 ChartView 1                            

原文:http://www.cnblogs.com/520myp1314/p/5311668.html


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!