IOS折线图
做项目要统计商品的销售情况,美工那边给了效果图,自己就按照效果图自定义了一个ScrollView。整体效果不错,在做的过程中遇到的问题也记录一下。
现在这个还有许多优化的地方:
1.一个表中只能画一个折线
2.目前的要求最小值为0,没考虑负数的最小值
// // LineChartView.h // chart // // Created by City--Online on 15/9/17. // Copyright © 2015年 City--Online. All rights reserved. // #import <UIKit/UIKit.h> //设置两点的水平间距 #define SPACING 70.0 //文本类型 typedef NS_ENUM(NSInteger, TitleType) { TitleForX, TitleForPoint }; @class LineChartView; @protocol LineChartDataSource <NSObject> @required //折点数量 -(NSInteger)numberForChart:(LineChartView *)chart; //折点数值 -(float)chart:(LineChartView *)chart valueAtIndex:(NSInteger)index; @optional //X轴坐标是否有背景色 -(BOOL)chart:(LineChartView *)chart backGroundColorAtXPointIndex:(NSInteger)index; //X 轴的标题 -(NSString *)chart:(LineChartView *)chart titleForXLabelAtIndex:(NSInteger)index; @end @interface LineChartView : UIScrollView @property(nonatomic,assign)id<LineChartDataSource> dataSource; @end
// // LineChartView.m // chart // // Created by City--Online on 15/9/17. // Copyright © 2015年 City--Online. All rights reserved. // #import "YZPLineChartView.h" @interface YZPLineChartView () @property (nonatomic,strong) CAShapeLayer * linePath; @property(nonatomic,assign)NSInteger maxValue; //最大值 @property(nonatomic,assign)NSInteger count; //点数 @property(nonatomic,assign)CGFloat avgHeight; //刻度 @end @implementation YZPLineChartView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor=[UIColor whiteColor]; _linePath=[CAShapeLayer layer]; _linePath.lineCap=kCALineCapRound; _linePath.lineJoin=kCALineJoinBevel; _linePath.lineWidth=; _linePath.fillColor=[UIColor clearColor].CGColor; self.bounces=NO; self.showsHorizontalScrollIndicator=NO; self.showsVerticalScrollIndicator=NO; _maxValue=; } return self; } //最大值 -(NSInteger)maxValue { ; i<self.count; i++) { NSInteger value=[_dataSource chart:self valueAtIndex:i]; _maxValue=value>_maxValue?value:_maxValue; } return _maxValue; } //点数 -(NSInteger)count { return [_dataSource numberForChart:self]; } //刻度 -(CGFloat)avgHeight { CGFloat height=self.frame.size.height; _avgHeight=(height--)/self.maxValue; return _avgHeight; } -(void)drawRect:(CGRect)rect { [super drawRect:rect]; //每次加载先删除原有图层 int count = [self.layer.sublayers count]; ; i<count; i++) { [self.layer.sublayers[] removeFromSuperlayer]; } //不能通过for in 删除 was mutated while being enumerated 遍历的时候不能删除 // for (CALayer *layer in self.layer.sublayers) { // [layer removeFromSuperlayer]; // } ) { return; } [self.layer addSublayer:_linePath]; self.contentSize=CGSizeMake((self.count)*SPACING, self.bounds.size.height); //画底部边线 [self drawVerticalLineStartPoint:CGPointMake(, self.bounds.size.height-) withEndPoint:CGPointMake(self.contentSize.width, self.bounds.size.height-) withColor:[UIColor grayColor] ]; //画折线 [self drawBrokenLine]; } //画底部边线 -(void)drawBottomLine { UIBezierPath *bottomLine=[UIBezierPath bezierPath]; [bottomLine moveToPoint:CGPointMake(, self.bounds.size.height-)]; [bottomLine addLineToPoint:CGPointMake(self.contentSize.width, self.bounds.size.height-)]; [[UIColor colorWithRed:0.902f green:0.902f blue:0.902f alpha:1.00f] setStroke]; [bottomLine stroke]; } //画竖线 -(void)drawVerticalLineStartPoint:(CGPoint) startPoint withEndPoint:(CGPoint) endPoint withColor:(UIColor *)color { CAShapeLayer *layer=[CAShapeLayer layer]; layer.lineCap=kCALineCapRound; layer.lineJoin=kCALineJoinBevel; layer.lineWidth=0.5; layer.fillColor=[UIColor clearColor].CGColor; [self.layer addSublayer:layer]; UIBezierPath *bottomLinePath=[UIBezierPath bezierPath]; [bottomLinePath moveToPoint:startPoint]; [bottomLinePath addLineToPoint:endPoint]; layer.path=bottomLinePath.CGPath; layer.strokeColor=[UIColor colorWithRed:0.902f green:0.902f blue:0.902f alpha:1.00f].CGColor; } //画点 -(void)drawPointWithCenterPoint:(CGPoint)point radius:(float)radius strokeColor:(UIColor *)strokeColor fillColor:(UIColor *)fillColor { UIBezierPath *drawPoint=[UIBezierPath bezierPath]; [drawPoint addArcWithCenter:point radius:radius startAngle:M_PI* endAngle:M_PI* clockwise:YES]; CAShapeLayer *layer=[[CAShapeLayer alloc]init]; layer.path=drawPoint.CGPath; layer.strokeColor=strokeColor.CGColor; layer.fillColor=fillColor.CGColor; [self.layer addSublayer:layer]; } // 画文字 原本使用[NSstring drawAtPoint: withAttributes:]方法 但是画之后并不随着ScrollView滚动 所以用Label -(void)drawText:(NSString *)text withPoint:(CGPoint)point withType:(TitleType) type withIndex:(NSInteger)index { CGRect frame=[text boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:.f]} context:nil]; UILabel *label=[[UILabel alloc]init]; CGPoint pointForValueString=CGPointMake(point.x-, point.y); ) { pointForValueString.y=point.y-frame.size.height-; } ) { pointForValueString.y=point.y+frame.size.height-; } label.frame=CGRectMake(pointForValueString.x, pointForValueString.y, , ); label.textAlignment=NSTextAlignmentCenter; if (type==TitleForPoint) { label.textColor=[UIColor redColor]; label.font=[UIFont systemFontOfSize:.f]; } else if (type==TitleForX) { label.frame=CGRectMake(pointForValueString.x, pointForValueString.y+, ,); if (_dataSource&&[_dataSource respondsToSelector:@selector(chart:backGroundColorAtXPointIndex:)]) { if ([_dataSource chart:self backGroundColorAtXPointIndex:index]) { label.backgroundColor=[UIColor redColor]; label.textColor=[UIColor whiteColor]; label.layer.cornerRadius=label.bounds.size.width/; label.clipsToBounds=YES; } else { label.backgroundColor=[UIColor whiteColor]; label.textColor=[UIColor colorWithRed:0.298f green:0.298f blue:0.298f alpha:1.00f]; } } else { label.textColor=[UIColor colorWithRed:0.298f green:0.298f blue:0.298f alpha:1.00f]; } label.font=[UIFont systemFontOfSize:.f]; } label.text=text; [self addSubview:label]; } -(void)drawBrokenLine { UIBezierPath *path=[UIBezierPath bezierPath]; ; i<self.count; i++) { CGFloat value=[_dataSource chart:self valueAtIndex:i]; CGPoint point=[self pointWithValue:value index:i]; //画竖线 [self drawVerticalLineStartPoint:CGPointMake((i+) withEndPoint:point withColor: [UIColor blueColor]]; //画折点 [self drawPointWithCenterPoint:point radius: strokeColor:[UIColor redColor] fillColor:self.backgroundColor]; //画X轴刻度点 UIColor *pointColor=[UIColor colorWithRed:0.902f green:0.902f blue:0.902f alpha:1.00f]; [self drawPointWithCenterPoint:CGPointMake((i+) radius: strokeColor:pointColor fillColor:pointColor]; //画文字 NSString *valueString=[NSString stringWithFormat:@"%ld",(long)value]; [self drawText:valueString withPoint:point withType:TitleForPoint withIndex:i]; //画X轴 if (_dataSource&&[_dataSource respondsToSelector:@selector(chart:titleForXLabelAtIndex:)]) { NSString *xstring=[_dataSource chart:self titleForXLabelAtIndex:i]; [self drawText:xstring withPoint:CGPointMake(point.x, self.bounds.size.height-) withType:TitleForX withIndex:i]; } //画折线 //贝塞尔曲线 ) { [path moveToPoint:point]; }else{ [path addLineToPoint:point]; } } path.lineCapStyle = kCGLineCapRound; path.lineJoinStyle=kCGLineJoinRound; path.lineWidth=0.5; [[UIColor redColor]setStroke]; CABasicAnimation *pathAnimation=[CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = ; pathAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; pathAnimation.fromValue=[NSNumber numberWithFloat:0.0f]; pathAnimation.toValue=[NSNumber numberWithFloat:1.0f]; pathAnimation.autoreverses=NO; _linePath.path=path.CGPath; _linePath.strokeColor=[UIColor redColor].CGColor; [_linePath addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; _linePath.strokeEnd = 1.0; } //根据索引计算出折点的位置 -(CGPoint)pointWithValue:(NSInteger)value index:(NSInteger)index { CGFloat height=self.frame.size.height; ); } @end
调用:
#import "ViewController.h" #import "LineChartView.h" @interface ViewController ()<LineChartDataSource> @property (nonatomic,strong) NSArray *points; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _points=@[@,@,@,@,@,@,@,@,@,@]; LineChartView *lineChart=[[LineChartView alloc]initWithFrame:CGRectMake(, , self.view.bounds.size.width, )]; lineChart.dataSource=self; [self.view addSubview:lineChart]; } -(NSInteger)numberForChart:(LineChartView *)chart { return _points.count; } -(float)chart:(LineChartView *)chart valueAtIndex:(NSInteger)index { return [[_points objectAtIndex:index] floatValue]; } -(NSString *)chart:(LineChartView *)chart titleForXLabelAtIndex:(NSInteger)index { return [NSString stringWithFormat:@"10%ld",index]; } -(BOOL)chart:(LineChartView *)chart backGroundColorAtXPointIndex:(NSInteger)index { ) { return true; } else { return false; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
效果:
IOS折线图的更多相关文章
- iOS 折线图、柱状图的简单实现
首先我得感谢某位博主,非常抱歉,因为之前直接下载博主提供这篇文章的demo,然后去研究了,没记住博主的名字.再次非常感谢. 而这个dome我又修改了一些,完善了一些不美观的bug,当然还有,后面会陆续 ...
- IOS折线图二
上周把项目的折线图给做了下,今天想着把它完善完善,自己设置了不同的数据源来测试,哈哈,还真遇到问题了, 就是给图表设置折点数为0时,视图显示的还是原来的,由于数据为空,应该将其设置为空,所以想着怎么把 ...
- iOS 折线图实现
图表绘制的过程实际上是坐标位置的计算过程,至于画线只要有了position,通过CAShapeLayer+BezierPath很快就可以画出来,这里提供一个绘制折线的demo,贵在思路,有需要的可以参 ...
- iOS绘制坐标图,折线图-Swift
坐标图,经常会在各种各样的App中使用,最常用的一种坐标图就是折线图,根据给定的点绘制出对应的坐标图是最基本的需求.由于本人的项目需要使用折线图,第一反应就是搜索已经存在的解决方案,因为这种需求应该很 ...
- iOS 动画绘制线条颜色渐变的折线图
效果图 .................... 概述 现状 折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图.折线图可以更加直观的表示数据的变化.网络上有很多绘制折线图的demo,有 ...
- IOS绘制渐变背景色折线图的一种尝试
1.绘制折线图 上次在群里看到一个折线图划的很漂亮,自己想实现一个这样的 ,但是一直没什么头绪,不知道怎么做,就开始在网上查找划线,绘 制渐变色这一块的内容,用最笨的方式,自己尝试的写了一些,也没 有 ...
- UUChart的使用--iOS绘制折线图
UUChart是一个用于绘制图表的第三方,尤其适合去绘制折线图. 二.下载地址: https://github.com/ZhipingYang/UUChartView 三.使用 第一步.首先我们将下载 ...
- IOS使用Core-Plot画折线图
关于Core-Plot的配置.大家能够參考我的上一篇博客:http://1.wildcat.sinaapp.com/?p=99 版权全部.转载请注明原文转自:http://blog.csdn.net/ ...
- iOS:使用贝塞尔曲线绘制图表(折线图、柱状图、饼状图)
1.介绍: UIBezierPath :画贝塞尔曲线的path类 UIBezierPath定义 : 贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度. 曲线的定义有四个点:起始点 ...
随机推荐
- VC6.0快捷键一览表
F1 显示帮助,如果光标停在代码的某个字符上,显示MSDN中相应的帮助内容 F2 书签功能: Ctrl+F2 –在某行设置一个书签(再按一次次是取消) F2 –跳到下一个书签位置 Shift+F2 – ...
- C# 多线程task
1.异步和多线程的区别?没什么太大区别.异步是目的,使用多线程实现.想想AJAX异步加载,不就是不想让浏览器界面卡住嘛,所以在程序中对于某些单独的操作,比如写日志,我们不想等它完成后再执行其它操作(因 ...
- AJPFX平台介绍
AJPFX设立于英国,业务框架扩展到欧洲.美洲和亚洲,在新加坡设有专门的亚洲地区服务部门.AJPFX旨在以极具竞争力的交易成本,也就是银行间市场核心点差和低水平的手续费,使客户在交易中获取最大的利润空 ...
- python网络编程--TCP连接的三次握手(三报文握手)与四次挥手
一.TCP连接 运输连接有三个阶段: 连接建立.数据传送和连接释放. 在TCP连接建立过程中要解决以下三个问题: 1,要使每一方能够确知对方的存在. 2.要允许双方协商一些参数(如最大窗口之,是否使用 ...
- JAVA的学习内容
http://www.weixueyuan.net/java/rumen/ 安卓学习文档 http://www.runoob.com/w3cnote/android-tutorial-linearla ...
- parseInt/类型转换/字符串
1.pa'rseInt整型 1.1parseInt必须以数字开头的 var topVal = parseInt("28px"); console.log(topVal); 1.2非 ...
- SQLAlchemy和Flask-SQLAlchemy
一.ORM 与 SQLAlchemy 简介 ORM 全称 Object Relational Mapping, 翻译过来叫对象关系映射.简单的说,ORM 将数据库中的表与面向对象语言中的类建立了一种对 ...
- blueborne漏洞的联想
本文作者:ice 0X00前言 昨天看到blueborne的漏洞,顺手给我的nexus6装了一个app,测试了一下,一脸懵逼,怎么修复啊,然后我联想了一下, 还有哪些协议和传输是我们身边的威胁了,于是 ...
- commonjs, nodejs, npm, browserify, watchify
CommonJS CommonJS是一套规范,定义了javascript API.其中为了解决javascript模块化的问题,引入require和export NodeJS nodeJS是服务器端j ...
- Java NIO学习与记录(三): Scatter&Gather介绍及使用
Scatter&Gather介绍及使用 上一篇知道了Buffer的工作机制,以及FileChannel的简单用法,这一篇介绍下 Scatter&Gather 1.Scatter(分散 ...