图表绘制的过程实际上是坐标位置的计算过程,至于画线只要有了position,通过CAShapeLayer+BezierPath很快就可以画出来,这里提供一个绘制折线的demo,贵在思路,有需要的可以参考

demo下载地址:https://github.com/qqcc1388/TYLineViewDemo

话不多说,效果图和代码

//单根折线实现

  1. #import <UIKit/UIKit.h>
  2. @interface TYLineView : UIView
  3. @property (nonatomic,strong) NSArray *datas;
  4. @property (nonatomic,strong) UIColor *lineColor;
  5. /**
  6. 是否显示灰色背景
  7. */
  8. @property (nonatomic,assign) BOOL isShowBack;
  9. @end
  10. #import "TYLineView.h"
  11. #define kMarginX 30
  12. #define kMarginY 20
  13. @interface TYLineView ()
  14. @property (nonatomic,strong)CAShapeLayer *shapeLayer;//划线layer
  15. @property (nonatomic,strong) CAShapeLayer *backLayer; //背景
  16. @property (nonatomic,assign)CGFloat maxYvalue; //最大y值
  17. @property (nonatomic,assign) NSInteger xAxisCount; //x轴点数
  18. @property (nonatomic,assign) NSInteger yAxisCount; //y轴点数
  19. @end
  20. @implementation TYLineView
  21. -(instancetype)initWithFrame:(CGRect)frame
  22. {
  23. if (self = [super initWithFrame:frame]) {
  24. [self initialize];
  25. }
  26. return self;
  27. }
  28. -(instancetype)initWithCoder:(NSCoder *)aDecoder
  29. {
  30. if (self = [super initWithCoder:aDecoder]) {
  31. [self initialize];
  32. }
  33. return self;
  34. }
  35. -(void)initialize
  36. {
  37. //闭合背景
  38. _backLayer = [[CAShapeLayer alloc] init];
  39. _backLayer.fillColor = [UIColor grayColor].CGColor;
  40. _backLayer.frame = self.bounds;
  41. [self.layer addSublayer:_backLayer];
  42. //主线段
  43. _shapeLayer = [[CAShapeLayer alloc] init];
  44. _shapeLayer.lineWidth = 1;
  45. _shapeLayer.lineCap = @"round";
  46. _shapeLayer.lineJoin = @"round";
  47. _shapeLayer.strokeColor = [UIColor redColor].CGColor;
  48. _shapeLayer.fillColor = [UIColor clearColor].CGColor;
  49. _shapeLayer.frame = self.bounds;
  50. [self.layer addSublayer:_shapeLayer];
  51. //初始化
  52. self.isShowBack = NO;
  53. self.yAxisCount = 5;
  54. self.backgroundColor = [UIColor cyanColor];
  55. }
  56. -(void)setDatas:(NSArray *)datas{
  57. //保存数据
  58. _datas = datas;
  59. //设置最大值
  60. self.maxYvalue = 200;
  61. //设置xAxisCount
  62. self.xAxisCount = datas.count;
  63. [self setNeedsDisplay];
  64. //划线
  65. [self drawLine];
  66. }
  67. -(void)drawLine
  68. {
  69. CGFloat totalHeight = CGRectGetHeight(self.frame) - kMarginY*2;
  70. // CGFloat maxY = self.maxYvalue;
  71. CGFloat totoalWidth = CGRectGetWidth(self.frame) - kMarginX*2;
  72. //x轴每一段的宽度
  73. CGFloat perX = totoalWidth/(self.xAxisCount-1)*1.0;
  74. CGFloat yper = totalHeight/self.maxYvalue; //y轴一个单位的高度
  75. //主线段曲线
  76. UIBezierPath *bezierPath = [UIBezierPath bezierPath];
  77. //背景曲线
  78. UIBezierPath *backPath = [UIBezierPath bezierPath];
  79. //原点
  80. CGPoint startPoint = CGPointMake(kMarginX,totalHeight + kMarginY);
  81. [backPath moveToPoint:startPoint];
  82. for (int i = 0; i < _datas.count; i++) {
  83. NSInteger valueY = [_datas[i] integerValue];
  84. CGFloat x = kMarginX + perX*i;
  85. CGFloat y = (totalHeight + kMarginY) - yper*valueY;
  86. CGPoint point = CGPointMake(x,y);
  87. if (i == 0) {
  88. [bezierPath moveToPoint:point];
  89. }else{
  90. [bezierPath addLineToPoint:point];
  91. }
  92. [backPath addLineToPoint:point];
  93. }
  94. //终点
  95. CGPoint endPoint = CGPointMake(kMarginX + perX*(self.datas.count-1), totalHeight + kMarginY);
  96. [backPath addLineToPoint:endPoint];
  97. //开始动画
  98. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  99. animation.duration = 2.0f;
  100. animation.removedOnCompletion = NO;
  101. animation.fillMode = kCAFillModeForwards;
  102. animation.fromValue = @(0);
  103. animation.toValue =@(1);
  104. self.shapeLayer.path = bezierPath.CGPath;
  105. [self.shapeLayer addAnimation:animation forKey:@"strokeEnd"];
  106. self.backLayer.path = backPath.CGPath;
  107. }
  108. -(void)drawRect:(CGRect)rect
  109. {
  110. [super drawRect:rect];
  111. UIBezierPath *path = [UIBezierPath bezierPath];
  112. [path setLineWidth:1.0f];
  113. [[UIColor redColor] set];
  114. CGFloat totalWidth = self.bounds.size.width;
  115. CGFloat totalHeight = self.bounds.size.height;
  116. //画坐标系
  117. //------> y轴
  118. [path moveToPoint:CGPointMake(kMarginX,kMarginY)];
  119. [path addLineToPoint:CGPointMake(kMarginX, totalHeight - kMarginY)];
  120. //------> x轴
  121. [path addLineToPoint:CGPointMake(totalWidth - kMarginX, totalHeight - kMarginY)];
  122. [path stroke];
  123. //线段 - y轴
  124. CGFloat perHeight = ((totalHeight - kMarginY*2)/(self.yAxisCount));
  125. for (int i = 0; i < self.yAxisCount; i++) {
  126. CGFloat y = perHeight*i + kMarginY;
  127. UIBezierPath *path = [UIBezierPath bezierPath];
  128. [path setLineWidth:1.0f];
  129. [[UIColor blueColor] set];
  130. [path moveToPoint:CGPointMake(kMarginX, y)];
  131. [path addLineToPoint:CGPointMake(kMarginX+ 5, y)];
  132. [path stroke];
  133. }
  134. //线段 - x轴
  135. CGFloat perWidth = (totalWidth - kMarginX*2)/(self.xAxisCount*1.0);
  136. for (int i = 0; i < self.xAxisCount; i++) {
  137. CGFloat x = perWidth*(i+1);
  138. CGFloat y = totalHeight - kMarginY;
  139. UIBezierPath *path = [UIBezierPath bezierPath];
  140. [path setLineWidth:1.0f];
  141. [[UIColor blueColor] set];
  142. [path moveToPoint:CGPointMake(x+kMarginX, y)];
  143. [path addLineToPoint:CGPointMake(x+kMarginX, y-5)];
  144. [path stroke];
  145. }
  146. //画y轴文字
  147. NSMutableArray *yArr = [NSMutableArray array];
  148. for (int i = 0; i < self.yAxisCount; i++) {
  149. [yArr addObject:[NSString stringWithFormat:@"%.f",self.maxYvalue - self.maxYvalue/self.yAxisCount *i]];
  150. }
  151. [yArr addObject:@"0"];
  152. for (int i = 0; i < yArr.count ; i++) {
  153. NSString *title = yArr[i];
  154. CGFloat y = ((totalHeight - kMarginY*2)/(self.yAxisCount))*i + kMarginY;
  155. NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
  156. [style setAlignment:NSTextAlignmentCenter];
  157. [title drawInRect:CGRectMake(0,y-5, kMarginX, 20) withAttributes:@{NSForegroundColorAttributeName:[UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:10],NSParagraphStyleAttributeName:style}];
  158. }
  159. }
  160. #pragma mark setter getter
  161. -(void)setLineColor:(UIColor *)lineColor{
  162. _lineColor = lineColor;
  163. self.shapeLayer.strokeColor = lineColor.CGColor;
  164. }
  165. -(void)setIsShowBack:(BOOL)isShowBack{
  166. _isShowBack = isShowBack;
  167. self.backLayer.hidden = !isShowBack;
  168. }

多根线一起

  1. #import <UIKit/UIKit.h>
  2. @interface TYMultiLineView : UIView
  3. -(void)addLineWithDatas:(NSArray *)datas lineColor:(UIColor *)color animated:(BOOL)animated;
  4. @end
  5. #import "TYMultiLineView.h"
  6. #define kMarginX 30
  7. #define kMarginY 20
  8. @interface TYMultiLineView ()
  9. @property (nonatomic,assign)CGFloat maxYvalue; //最大y值
  10. @property (nonatomic,assign) NSInteger xAxisCount; //x轴点数
  11. @property (nonatomic,assign) NSInteger yAxisCount; //y轴点数
  12. @end
  13. @implementation TYMultiLineView
  14. -(instancetype)initWithFrame:(CGRect)frame
  15. {
  16. if (self = [super initWithFrame:frame]) {
  17. [self initialize];
  18. }
  19. return self;
  20. }
  21. -(instancetype)initWithCoder:(NSCoder *)aDecoder
  22. {
  23. if (self = [super initWithCoder:aDecoder]) {
  24. [self initialize];
  25. }
  26. return self;
  27. }
  28. -(void)initialize
  29. {
  30. self.backgroundColor = [UIColor cyanColor];
  31. self.maxYvalue = 200;
  32. self.yAxisCount = 5;
  33. self.xAxisCount = 5;
  34. [self setNeedsDisplay];
  35. }
  36. -(void)addLineWithDatas:(NSArray *)datas lineColor:(UIColor *)color animated:(BOOL)animated{
  37. //设置最大值
  38. self.maxYvalue = 200;
  39. //设置xAxisCount
  40. self.xAxisCount = datas.count;
  41. CAShapeLayer* lineLayer = [[CAShapeLayer alloc] init];
  42. lineLayer.lineWidth = 1;
  43. lineLayer.lineCap = @"round";
  44. lineLayer.lineJoin = @"round";
  45. lineLayer.strokeColor = color.CGColor;
  46. lineLayer.fillColor = [UIColor clearColor].CGColor;
  47. lineLayer.frame = self.bounds;
  48. [self.layer addSublayer:lineLayer];
  49. UIBezierPath *path = [self prepareBezierPathDatas:datas];
  50. lineLayer.path = path.CGPath;
  51. if(animated){
  52. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  53. animation.duration = 2.0f;
  54. animation.removedOnCompletion = NO;
  55. animation.fillMode = kCAFillModeForwards;
  56. animation.fromValue = @(0);
  57. animation.toValue =@(1);
  58. [lineLayer addAnimation:animation forKey:@"strokeEnd"];
  59. }
  60. }
  61. -(UIBezierPath *)prepareBezierPathDatas:(NSArray *)datas
  62. {
  63. CGFloat totalHeight = CGRectGetHeight(self.frame) - kMarginY*2;
  64. // CGFloat maxY = self.maxYvalue;
  65. CGFloat totoalWidth = CGRectGetWidth(self.frame) - kMarginX*2;
  66. //x轴每一段的宽度
  67. CGFloat perX = totoalWidth/(self.xAxisCount-1)*1.0;
  68. CGFloat yper = totalHeight/self.maxYvalue; //y轴一个单位的高度
  69. //主线段曲线
  70. UIBezierPath *bezierPath = [UIBezierPath bezierPath];
  71. for (int i = 0; i < datas.count; i++) {
  72. NSInteger valueY = [datas[i] integerValue];
  73. CGFloat x = kMarginX + perX*i;
  74. CGFloat y = (totalHeight + kMarginY) - yper*valueY;
  75. CGPoint point = CGPointMake(x,y);
  76. if (i == 0) {
  77. [bezierPath moveToPoint:point];
  78. }else{
  79. [bezierPath addLineToPoint:point];
  80. }
  81. }
  82. return bezierPath;
  83. }
  84. -(void)drawRect:(CGRect)rect
  85. {
  86. [super drawRect:rect];
  87. UIBezierPath *path = [UIBezierPath bezierPath];
  88. [path setLineWidth:1.0f];
  89. [[UIColor redColor] set];
  90. CGFloat totalWidth = self.bounds.size.width;
  91. CGFloat totalHeight = self.bounds.size.height;
  92. //画坐标系
  93. //------> y轴
  94. [path moveToPoint:CGPointMake(kMarginX,kMarginY)];
  95. [path addLineToPoint:CGPointMake(kMarginX, totalHeight - kMarginY)];
  96. //------> x轴
  97. [path addLineToPoint:CGPointMake(totalWidth - kMarginX, totalHeight - kMarginY)];
  98. [path stroke];
  99. //线段 - y轴
  100. CGFloat perHeight = ((totalHeight - kMarginY*2)/(self.yAxisCount));
  101. for (int i = 0; i < self.yAxisCount; i++) {
  102. CGFloat y = perHeight*i + kMarginY;
  103. UIBezierPath *path = [UIBezierPath bezierPath];
  104. [path setLineWidth:1.0f];
  105. [[UIColor blueColor] set];
  106. [path moveToPoint:CGPointMake(kMarginX, y)];
  107. [path addLineToPoint:CGPointMake(kMarginX+ 5, y)];
  108. [path stroke];
  109. }
  110. //线段 - x轴
  111. CGFloat perWidth = (totalWidth - kMarginX*2)/(self.xAxisCount*1.0);
  112. for (int i = 0; i < self.xAxisCount; i++) {
  113. CGFloat x = perWidth*(i+1);
  114. CGFloat y = totalHeight - kMarginY;
  115. UIBezierPath *path = [UIBezierPath bezierPath];
  116. [path setLineWidth:1.0f];
  117. [[UIColor blueColor] set];
  118. [path moveToPoint:CGPointMake(x+kMarginX, y)];
  119. [path addLineToPoint:CGPointMake(x+kMarginX, y-5)];
  120. [path stroke];
  121. }
  122. //画y轴文字
  123. NSMutableArray *yArr = [NSMutableArray array];
  124. for (int i = 0; i < self.yAxisCount; i++) {
  125. [yArr addObject:[NSString stringWithFormat:@"%.f",self.maxYvalue - self.maxYvalue/self.yAxisCount *i]];
  126. }
  127. [yArr addObject:@"0"];
  128. for (int i = 0; i < yArr.count ; i++) {
  129. NSString *title = yArr[i];
  130. CGFloat y = ((totalHeight - kMarginY*2)/(self.yAxisCount))*i + kMarginY;
  131. NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
  132. [style setAlignment:NSTextAlignmentCenter];
  133. [title drawInRect:CGRectMake(0,y-5, kMarginX, 20) withAttributes:@{NSForegroundColorAttributeName:[UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:10],NSParagraphStyleAttributeName:style}];
  134. }
  135. }

使用方法

  1. lineView:
  2. [self.lineView setDatas:[self prepareDatas]];
  3. multiLineView:
  4. [self.multiLineView addLineWithDatas:[self prepareDatas] lineColor:[UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1] animated:YES];
  5. -(NSArray *)prepareDatas{
  6. NSMutableArray *datas = [NSMutableArray array];
  7. for (int i = 0; i < 5; i++) {
  8. [datas addObject:@(arc4random_uniform(201)).stringValue];
  9. }
  10. return datas;
  11. }

关于动画画线方法:给shapelayer添加strokeEnd动画

  1. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  2. animation.duration = 2.0f;
  3. animation.removedOnCompletion = NO;
  4. animation.fillMode = kCAFillModeForwards;
  5. animation.fromValue = @(0);
  6. animation.toValue =@(1);
  7. [lineLayer addAnimation:animation forKey:@"strokeEnd"];

demo中还有很多地方需要完善,这里仅仅是抛砖引玉提供一种实现的方案,细节的处理和其他的特殊需求请参考demo,自己进行拓展

iOS 折线图实现的更多相关文章

  1. iOS 折线图、柱状图的简单实现

    首先我得感谢某位博主,非常抱歉,因为之前直接下载博主提供这篇文章的demo,然后去研究了,没记住博主的名字.再次非常感谢. 而这个dome我又修改了一些,完善了一些不美观的bug,当然还有,后面会陆续 ...

  2. IOS折线图二

    上周把项目的折线图给做了下,今天想着把它完善完善,自己设置了不同的数据源来测试,哈哈,还真遇到问题了, 就是给图表设置折点数为0时,视图显示的还是原来的,由于数据为空,应该将其设置为空,所以想着怎么把 ...

  3. IOS折线图

    做项目要统计商品的销售情况,美工那边给了效果图,自己就按照效果图自定义了一个ScrollView.整体效果不错,在做的过程中遇到的问题也记录一下. 现在这个还有许多优化的地方: 1.一个表中只能画一个 ...

  4. iOS绘制坐标图,折线图-Swift

    坐标图,经常会在各种各样的App中使用,最常用的一种坐标图就是折线图,根据给定的点绘制出对应的坐标图是最基本的需求.由于本人的项目需要使用折线图,第一反应就是搜索已经存在的解决方案,因为这种需求应该很 ...

  5. iOS 动画绘制线条颜色渐变的折线图

    效果图 .................... 概述 现状 折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图.折线图可以更加直观的表示数据的变化.网络上有很多绘制折线图的demo,有 ...

  6. IOS绘制渐变背景色折线图的一种尝试

    1.绘制折线图 上次在群里看到一个折线图划的很漂亮,自己想实现一个这样的 ,但是一直没什么头绪,不知道怎么做,就开始在网上查找划线,绘 制渐变色这一块的内容,用最笨的方式,自己尝试的写了一些,也没 有 ...

  7. UUChart的使用--iOS绘制折线图

    UUChart是一个用于绘制图表的第三方,尤其适合去绘制折线图. 二.下载地址: https://github.com/ZhipingYang/UUChartView 三.使用 第一步.首先我们将下载 ...

  8. IOS使用Core-Plot画折线图

    关于Core-Plot的配置.大家能够參考我的上一篇博客:http://1.wildcat.sinaapp.com/?p=99 版权全部.转载请注明原文转自:http://blog.csdn.net/ ...

  9. iOS:使用贝塞尔曲线绘制图表(折线图、柱状图、饼状图)

    1.介绍: UIBezierPath :画贝塞尔曲线的path类 UIBezierPath定义 : 贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度. 曲线的定义有四个点:起始点 ...

随机推荐

  1. Kafka 源代码分析之LogSegment

    这里分析kafka LogSegment源代码 通过一步步分析LogManager,Log源代码之后就会发现,最终的log操作都在LogSegment上实现.LogSegment负责分片的读写恢复刷新 ...

  2. java怎么处理json数据

    json = new JSONObject(data); int which = json.optInt("which", -1); String label = json.opt ...

  3. Mathematica学习笔记1

    非常喜欢Mathematica的"自动草稿纸"的理念,Magic Paper, 唔哈~ Mathematica的矩阵操作和Matlab的风格十分不同. [ ] 是一个Part运算符 ...

  4. python自动化运维学习第一天--day1

    学习python自动化运维第一天自己总结的作业 所使用到知识:json模块,用于数据转化sys.exit 用于中断循环退出程序字符串格式化.format字典.文件打开读写with open(file, ...

  5. Python查看MQ队列深度

    分享一段代码,很简单但是也很实用. #!/usr/bin/python #-*- coding:gb18030 -*- ''' Usage: mq.py [Qmgr] *get the queues' ...

  6. xtrabackup备份mysql数据库的使用方法

    xtrabackup是由percona提供的mysql备份工具,它是一款物理备份工具,通过连接数据库把数据库的数据备份出来.对于innodb存储引擎其支持全量备份和增量备份.对于myisam存储引擎只 ...

  7. JavaScript创建对象的方法

    显示在浏览器中的控制台中. <script type="text/javascript"> //这个工厂方法返回一个新的"范围对象" functio ...

  8. hdu_1907:John(Nim变形)

    题目链接 仍是取石子,不过取到最后一个的败 参考链接:http://www.voidcn.com/blog/liwen_7/article/p-3341825.html 简单一句话就是T2 S0必败 ...

  9. Python基础之字符编码

    前言 字符编码非常容易出问题,我们要牢记几句话: 1.用什么编码保存的,就要用什么编码打开 2.程序的执行,是先将文件读入内存中 3.unicode是父编码,只能encode解码成其他编码格式 utf ...

  10. POJ 2566 尺取法(进阶题)

    Bound Found Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4297   Accepted: 1351   Spe ...