IOS折线统计图
来源:互联网 发布:手机短信轰炸机源码 编辑:程序博客网 时间:2024/05/22 11:59
做项目要统计商品的销售情况,美工那边给了效果图,自己就按照效果图自定义了一个ScrollView。整体效果不错,在做的过程中遇到的问题也记录一下。
现在这个还有许多优化的地方:
1.一个表中只能画一个折线
2.目前的要求最小值为0,没考虑负数的最小值
//// LineChartView.h// CAShapeLayerTest//// Created by Mkil on 3/31/16.// Copyright © 2016 Mkil. All rights reserved.//#import <UIKit/UIKit.h>#define SPACING 70.0 //设置两点的水平间距#define BOTTOMSPACING 60.0 //底部距离#define LEFTSPACING 80.0 //左边距离//文本类型typedef NS_ENUM(NSInteger, TitleType) { TitleForX, TitleForPoint, TitelForNormal};@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;@property (nonatomic, assign) NSInteger maxValue;@end
//// LineChartView.m// CAShapeLayerTest//// Created by Mkil on 3/31/16.// Copyright © 2016 Mkil. All rights reserved.//#import "LineChartView.h"#define textDColor [UIColor colorWithRed:255/255.0 green:164/255.0 blue:102/255.0 alpha:1]#define line228Color [UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1]@interface LineChartView ()@property (nonatomic, strong) CAShapeLayer *linePath;@property (nonatomic, assign) NSInteger count; //点数@property (nonatomic, assign) CGFloat avgHeight; //刻度@end@implementation LineChartView- (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 = 2; _linePath.fillColor = [UIColor clearColor].CGColor; self.bounces=NO;// self.backgroundColor = [UIColor lightGrayColor]; self.showsHorizontalScrollIndicator=NO; self.showsVerticalScrollIndicator=NO; } return self;}//点数-(NSInteger)count{ return [_dataSource numberForChart:self];}//刻度-(CGFloat)avgHeight{ CGFloat height=self.frame.size.height; _avgHeight=(height-40-20)/self.maxValue; return _avgHeight;}- (void)drawRect:(CGRect)rect{ [super drawRect:rect]; NSInteger count = [self.layer.sublayers count]; for (int i = 0; i < count ; i ++) { [self.layer.sublayers[i] removeFromSuperlayer]; } //不能通过for in 删除 was mutated while being enumerated 遍历的时候不能删除 // for (CALayer *layer in self.layer.sublayers) { // [layer removeFromSuperlayer]; // } if (self.count <= 0) { return; } [self.layer addSublayer:_linePath]; self.contentSize=CGSizeMake((self.count)*SPACING + LEFTSPACING, self.bounds.size.height); //画横线 [self drawTransverseLineHeight:self.frame.size.height - 40]; [self drawTransverseLineHeight:20]; [self drawTransverseLineHeight:20 + (self.frame.size.height - 40 - 20)/2.0]; //画文字 CGPoint point = CGPointMake(40, 20); [self drawText:[NSString stringWithFormat:@"%ld",self.maxValue] withPoint:point withType:TitelForNormal withColor:line228Color withIndex:1]; point = CGPointMake(40, 20 + (self.frame.size.height - 40 - 20)/2.0); [self drawText:[NSString stringWithFormat:@"%ld",self.maxValue/2] withPoint:point withType:TitelForNormal withColor:line228Color withIndex:1]; //画折线 [self drawBrokenLine]; }//画横线- (void)drawTransverseLineHeight:(CGFloat) height{ CAShapeLayer *layer=[CAShapeLayer layer]; layer.lineCap=kCALineCapRound; layer.lineJoin=kCALineJoinBevel; layer.lineWidth=0.1; layer.fillColor=[UIColor clearColor].CGColor; [self.layer addSublayer:layer]; UIBezierPath *transverseLine = [UIBezierPath bezierPath]; [transverseLine moveToPoint:CGPointMake(20, height)]; [transverseLine addLineToPoint:CGPointMake(self.contentSize.width - 20, height)]; layer.path = transverseLine.CGPath; layer.strokeColor = [UIColor blackColor].CGColor;}//画竖线-(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)drawText:(NSString *)text withPoint:(CGPoint)point withType:(TitleType) type withColor:(UIColor *)textColor withIndex:(NSInteger)index{ CGRect frame=[text boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:10.f]} context:nil]; UILabel *label=[[UILabel alloc]init]; CGPoint pointForValueString=CGPointMake(point.x-15, point.y); if (pointForValueString.y+frame.size.height>self.frame.size.height-50) { pointForValueString.y=point.y-frame.size.height-20; } else if (pointForValueString.y-frame.size.height<0) { pointForValueString.y=point.y+frame.size.height-20; } label.frame=CGRectMake(pointForValueString.x - 15, pointForValueString.y, 60, 30); label.textAlignment=NSTextAlignmentCenter; if (type==TitleForPoint) { label.textColor=textColor; label.font=[UIFont systemFontOfSize:13.f]; } else if (type==TitleForX) { label.frame=CGRectMake(pointForValueString.x, pointForValueString.y+15, 30,30); if (_dataSource&&[_dataSource respondsToSelector:@selector(chart:backGroundColorAtXPointIndex:)]) { if ([_dataSource chart:self backGroundColorAtXPointIndex:index]) { label.backgroundColor=textColor; label.textColor=[UIColor whiteColor]; label.layer.cornerRadius=label.bounds.size.width/2; 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:14.f]; }else if (type == TitelForNormal) { label.textColor=textColor; label.font=[UIFont systemFontOfSize:18.f]; } label.text=text; [self addSubview:label];}- (void)drawBrokenLine{ UIBezierPath *path = [UIBezierPath bezierPath]; for (int i=0; i < self.count; i++) { CGFloat value = [_dataSource chart:self valueAtIndex:i]; CGPoint point = [self pointWithValue:value index:i]; //画竖线 if (i == 0) { [self drawVerticalLineStartPoint:CGPointMake(LEFTSPACING, self.frame.size.height-40) withEndPoint:CGPointMake(LEFTSPACING, self.frame.size.height - 30) withColor: [UIColor blueColor]]; [self drawVerticalLineStartPoint:CGPointMake(LEFTSPACING, self.frame.size.height-40) withEndPoint:point withColor: [UIColor blueColor]]; }else{ [self drawVerticalLineStartPoint:CGPointMake(i*SPACING + LEFTSPACING, self.frame.size.height-40) withEndPoint:CGPointMake(i*SPACING + LEFTSPACING, self.frame.size.height - 30) withColor: [UIColor blueColor]]; [self drawVerticalLineStartPoint:CGPointMake(i*SPACING + LEFTSPACING, self.frame.size.height-40) withEndPoint:point withColor: [UIColor blueColor]]; } //画文字 NSString *valueString=[NSString stringWithFormat:@"%ld",(long)value]; [self drawText:valueString withPoint:point withType:TitleForPoint withColor:textDColor 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-10) withType:TitleForX withColor:line228Color withIndex:i]; } //画折线 //贝塞尔曲线 if (i==0) { [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 = 2; 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=textDColor.CGColor; [_linePath addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; _linePath.strokeEnd = 1.0;}//根据索引计算出折点的位置-(CGPoint)pointWithValue:(NSInteger)value index:(NSInteger)index{ CGFloat height=self.frame.size.height; if (index == 0) { return CGPointMake(LEFTSPACING, height-value*self.avgHeight-40); } return CGPointMake(index*SPACING + LEFTSPACING, height-value*self.avgHeight-40);}@end
调用:
//// ViewController.m// CAShapeLayerTest//// Created by Mkil on 3/31/16.// Copyright © 2016 Mkil. All rights reserved.//#import "ViewController.h"#import "LineChartView.h"@interface ViewController ()<LineChartDataSource>@property (nonatomic ,strong) NSArray *points;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.view.backgroundColor = [UIColor whiteColor]; _points=@[@3000,@400,@2500,@3500,@1800,@2800,@900,@3400,@2900,@3100,@3000,@2500]; LineChartView *lineChart=[[LineChartView alloc]initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, 300)]; lineChart.dataSource=self; lineChart.maxValue = 4000; [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:@"%ld",index*2];}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end
效果:
1 0
- IOS折线统计图
- 统计图折线
- iOS 带渐变背景动画的折线统计图
- C# 做折线统计图
- 自定义折线统计图
- 自定义折线统计图
- 画一个折线统计图
- perl-制作统计图(折线)
- 使用QWT实现折线统计图
- LineChartView—自定义折线统计图
- 可视化库Matplotlib-折线统计图
- C# 绘制统计图(折线,柱状图,饼图)
- 跟随统计图扩展的折线图:
- C#+统计图-柱形图+饼形图+折线图
- Android自定义统计图(柱状图,折线图,饼状图)
- Android自定义统计图(柱状图,折线图,饼状图)
- Android自定义统计图(柱状图,折线图,饼状图)
- Android自定义统计图(柱状图,折线图,饼状图)
- 压缩包里面excel 导出 (跨行跨列)
- Android实现获取短信验证码的功能以及自定义GUI短信验证
- Codeforces Round #346 (Div. 2)--A. Round House
- SecurCRT命令回显设置
- ssh 无密码登陆
- IOS折线统计图
- POJ 1019 数论基础题
- 通过url地址获取数据后将数据利用SpringMVC的@ResponseBody返回中文可能出现乱码地方
- iOS之隐藏/显示tabbar
- Eclipse常用设置
- java和js实现aes加密解密
- 各种字符的限制输入
- dreamweaver制作静态网页第一天
- 【OpenCV】OpenCV3的第三天——core组件