// // JHLineChart.m // JHChartDemo // // Created by cjatech-简豪 on 16/4/10. // Copyright © 2016年 JH. All rights reserved. // #import "JHLineChart.h" #define kXandYSpaceForSuperView 20.0 @interface JHLineChart () @property (assign, nonatomic) CGFloat xLength; @property (assign , nonatomic) CGFloat yLength; @property (assign , nonatomic) CGFloat perXLen ; @property (assign , nonatomic) CGFloat perYlen ; @property (assign , nonatomic) CGFloat perValue ; @property (nonatomic,strong) NSMutableArray * drawDataArr; @property (nonatomic,strong) CAShapeLayer *shapeLayer; @property (assign , nonatomic) BOOL isEndAnimation ; @property (nonatomic,strong) NSMutableArray * layerArr; @end @implementation JHLineChart /** * 重写初始化方法 * * @param frame frame * @param lineChartType 折线图类型 * * @return 自定义折线图 */ -(instancetype)initWithFrame:(CGRect)frame andLineChartType:(JHLineChartType)lineChartType { if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor colorWithRed:0.2 green:0.7 blue:0.2 alpha:0.3]; _lineType = lineChartType; _lineWidth = 5; // 线条宽度 self.contentInsets = UIEdgeInsetsMake(10, 20, 10, 10); _yLineDataArr = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7"]; _xLineDataArr = @[@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7"]; _xAndYLineColor = [UIColor darkGrayColor]; _pointNumberColorArr = @[[UIColor redColor]]; _positionLineColorArr = @[[UIColor darkGrayColor]]; _pointColorArr = @[[UIColor orangeColor]]; _xAndYNumberColor = [UIColor darkGrayColor]; _valueLineColorArr = @[[UIColor redColor]]; _layerArr = [NSMutableArray array]; _showYLine = YES; _showYLevelLine = NO; _showValueLeadingLine = YES; // _contentFillColorArr = @[[UIColor lightGrayColor]]; [self configChartXAndYLength]; [self configChartOrigin]; [self configPerXAndPerY]; } return self; } /** * 清除图标内容 */ -(void)clear{ _valueArr = nil; _drawDataArr = nil; for (CALayer *layer in _layerArr) { [layer removeFromSuperlayer]; } [self showAnimation]; } /** * 获取每个X或y轴刻度间距 */ - (void)configPerXAndPerY { switch (_lineChartQuadrantType) { case JHLineChartQuadrantTypeFirstQuardrant: { _perXLen = (_xLength-kXandYSpaceForSuperView)/(_xLineDataArr.count-1); _perYlen = (_yLength-kXandYSpaceForSuperView)/_yLineDataArr.count; } break; case JHLineChartQuadrantTypeFirstAndSecondQuardrant: { _perXLen = (_xLength/2-kXandYSpaceForSuperView)/[_xLineDataArr[0] count]; _perYlen = (_yLength-kXandYSpaceForSuperView)/_yLineDataArr.count; } break; case JHLineChartQuadrantTypeFirstAndFouthQuardrant: { _perXLen = (_xLength-kXandYSpaceForSuperView)/(_xLineDataArr.count-1); _perYlen = (_yLength/2-kXandYSpaceForSuperView)/[_yLineDataArr[0] count]; } break; case JHLineChartQuadrantTypeAllQuardrant: { _perXLen = (_xLength/2-kXandYSpaceForSuperView)/([_xLineDataArr[0] count]); _perYlen = (_yLength/2-kXandYSpaceForSuperView)/[_yLineDataArr[0] count]; } break; default: break; } } /** * 重写LineChartQuardrantType的setter方法 动态改变折线图原点 * */ -(void)setLineChartQuadrantType:(JHLineChartQuadrantType)lineChartQuadrantType{ _lineChartQuadrantType = lineChartQuadrantType; [self configChartOrigin]; } /** * 获取X与Y轴的长度 */ - (void)configChartXAndYLength{ _xLength = CGRectGetWidth(self.frame)-self.contentInsets.left-self.contentInsets.right; _yLength = CGRectGetHeight(self.frame)-self.contentInsets.top-self.contentInsets.bottom; } /** * 重写ValueArr的setter方法 赋值时改变Y轴刻度大小 * */ -(void)setValueArr:(NSArray *)valueArr { _valueArr = valueArr; [self updateYScale]; } /** * 更新Y轴的刻度大小 */ - (void)updateYScale{ switch (_lineChartQuadrantType) { case JHLineChartQuadrantTypeFirstAndFouthQuardrant: { NSInteger max = 0; NSInteger min = 0; for (NSArray *arr in _valueArr) { for (NSString * numer in arr) { NSInteger i = [numer integerValue]; if (i>=max) { max = i; } if (i<=min) { min = i; } } } min = labs(min); max = (min5) { for (NSInteger i = 0; i<5; i++) { [arr addObject:[NSString stringWithFormat:@"%ld",(i+1)*2]]; [minArr addObject:[NSString stringWithFormat:@"-%ld",(i+1)*2]]; } }else if(max>10&&max<=100){ for (NSInteger i = 0; i=max) { max = i; } if (i<=min) { min = i; } } } min = labs(min); max = (min5) { for (NSInteger i = 0; i<5; i++) { [arr addObject:[NSString stringWithFormat:@"%ld",(i+1)*2]]; [minArr addObject:[NSString stringWithFormat:@"-%ld",(i+1)*2]]; } }else if(max>10&&max<=100){ for (NSInteger i = 0; i=max) { max = i; } } } if (max%5==0) { max = max; }else max = (max/5+1)*5; _yLineDataArr = nil; NSMutableArray *arr = [NSMutableArray array]; if (max<=5) { for (NSInteger i = 0; i<5; i++) { [arr addObject:[NSString stringWithFormat:@"%ld",(i+1)*1]]; } } if (max<=10&&max>5) { for (NSInteger i = 0; i<5; i++) { [arr addObject:[NSString stringWithFormat:@"%ld",(i+1)*2]]; } }else if(max>10&&max<=50){ for (NSInteger i = 0; i 100){ NSInteger count = max / 10; for (NSInteger i = 0; i<10+1; i++) { [arr addObject:[NSString stringWithFormat:@"%ld",(i+1)*count]]; } } _yLineDataArr = [arr copy]; [self setNeedsDisplay]; } } break; } } /** * 构建折线图原点 */ - (void)configChartOrigin{ switch (_lineChartQuadrantType) { case JHLineChartQuadrantTypeFirstQuardrant: { self.chartOrigin = CGPointMake(self.contentInsets.left, self.frame.size.height-self.contentInsets.bottom); } break; case JHLineChartQuadrantTypeFirstAndSecondQuardrant: { self.chartOrigin = CGPointMake(self.contentInsets.left+_xLength/2, CGRectGetHeight(self.frame)-self.contentInsets.bottom); } break; case JHLineChartQuadrantTypeFirstAndFouthQuardrant: { self.chartOrigin = CGPointMake(self.contentInsets.left, self.contentInsets.top+_yLength/2); } break; case JHLineChartQuadrantTypeAllQuardrant: { self.chartOrigin = CGPointMake(self.contentInsets.left+_xLength/2, self.contentInsets.top+_yLength/2); } break; default: break; } } /* 绘制x与y轴 */ - (void)drawXAndYLineWithContext:(CGContextRef)context{ switch (_lineChartQuadrantType) { case JHLineChartQuadrantTypeFirstQuardrant:{ [self drawLineWithContext:context andStarPoint:self.chartOrigin andEndPoint:P_M(self.contentInsets.left+_xLength, self.chartOrigin.y) andIsDottedLine:NO andColor:_xAndYLineColor]; if (_showYLine) { [self drawLineWithContext:context andStarPoint:self.chartOrigin andEndPoint:P_M(self.chartOrigin.x,self.chartOrigin.y-_yLength) andIsDottedLine:NO andColor:_xAndYLineColor]; } if (_xLineDataArr.count>0) { CGFloat xPace = (_xLength-kXandYSpaceForSuperView)/(_xLineDataArr.count-1); for (NSInteger i = 0; i<_xLineDataArr.count;i++ ) { CGPoint p = P_M(i*xPace+self.chartOrigin.x, self.chartOrigin.y); CGFloat len = [self getTextWithWhenDrawWithText:_xLineDataArr[i]]; [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x, p.y-3) andIsDottedLine:NO andColor:_xAndYLineColor]; [self drawText:[NSString stringWithFormat:@"%@",_xLineDataArr[i]] andContext:context atPoint:P_M(p.x-len/2, p.y+2) WithColor:_xAndYNumberColor andFontSize:7.0]; } } if (_yLineDataArr.count>0) { CGFloat yPace = (_yLength - kXandYSpaceForSuperView)/(_yLineDataArr.count); for (NSInteger i = 0; i<_yLineDataArr.count; i++) { CGPoint p = P_M(self.chartOrigin.x, self.chartOrigin.y - (i+1)*yPace); CGFloat len = [self getTextWithWhenDrawWithText:_yLineDataArr[i]]; if (_showYLevelLine) { [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:NO andColor:_xAndYLineColor]; }else{ [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x+3, p.y) andIsDottedLine:NO andColor:_xAndYLineColor]; } [self drawText:[NSString stringWithFormat:@"%@",_yLineDataArr[i]] andContext:context atPoint:P_M(p.x-len-3, p.y-3) WithColor:_xAndYNumberColor andFontSize:7.0]; } } }break; case JHLineChartQuadrantTypeFirstAndSecondQuardrant:{ [self drawLineWithContext:context andStarPoint:P_M(self.contentInsets.left, self.chartOrigin.y) andEndPoint:P_M(self.contentInsets.left+_xLength, self.chartOrigin.y) andIsDottedLine:NO andColor:_xAndYLineColor]; if (_showYLine) { [self drawLineWithContext:context andStarPoint:self.chartOrigin andEndPoint:P_M(self.chartOrigin.x,self.chartOrigin.y-_yLength) andIsDottedLine:NO andColor:_xAndYLineColor]; } if (_xLineDataArr.count == 2) { NSArray * rightArr = _xLineDataArr[1]; NSArray * leftArr = _xLineDataArr[0]; CGFloat xPace = (_xLength/2-kXandYSpaceForSuperView)/(rightArr.count-1); for (NSInteger i = 0; i0) { CGFloat yPace = (_yLength - kXandYSpaceForSuperView)/(_yLineDataArr.count); for (NSInteger i = 0; i<_yLineDataArr.count; i++) { CGPoint p = P_M(self.chartOrigin.x, self.chartOrigin.y - (i+1)*yPace); CGFloat len = [self getTextWithWhenDrawWithText:_yLineDataArr[i]]; if (_showYLevelLine) { [self drawLineWithContext:context andStarPoint:P_M(self.contentInsets.left, p.y) andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:NO andColor:_xAndYLineColor]; }else [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x+3, p.y) andIsDottedLine:NO andColor:_xAndYLineColor]; [self drawText:[NSString stringWithFormat:@"%@",_yLineDataArr[i]] andContext:context atPoint:P_M(p.x-len-3, p.y-3) WithColor:_xAndYNumberColor andFontSize:7.0]; } } }break; case JHLineChartQuadrantTypeFirstAndFouthQuardrant:{ [self drawLineWithContext:context andStarPoint:self.chartOrigin andEndPoint:P_M(self.contentInsets.left+_xLength, self.chartOrigin.y) andIsDottedLine:NO andColor:_xAndYLineColor]; if (_showYLine) { [self drawLineWithContext:context andStarPoint:P_M(self.contentInsets.left,CGRectGetHeight(self.frame)-self.contentInsets.bottom) andEndPoint:P_M(self.chartOrigin.x,self.contentInsets.top) andIsDottedLine:NO andColor:_xAndYLineColor]; } if (_xLineDataArr.count>0) { CGFloat xPace = (_xLength-kXandYSpaceForSuperView)/(_xLineDataArr.count-1); for (NSInteger i = 0; i<_xLineDataArr.count;i++ ) { CGPoint p = P_M(i*xPace+self.chartOrigin.x, self.chartOrigin.y); CGFloat len = [self getTextWithWhenDrawWithText:_xLineDataArr[i]]; [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x, p.y-3) andIsDottedLine:NO andColor:_xAndYLineColor]; if (i==0) { len = -2; } [self drawText:[NSString stringWithFormat:@"%@",_xLineDataArr[i]] andContext:context atPoint:P_M(p.x-len/2, p.y+2) WithColor:_xAndYNumberColor andFontSize:7.0]; } } if (_yLineDataArr.count == 2) { NSArray * topArr = _yLineDataArr[0]; NSArray * bottomArr = _yLineDataArr[1]; CGFloat yPace = (_yLength/2 - kXandYSpaceForSuperView)/([_yLineDataArr[0] count]); _perYlen = yPace; for (NSInteger i = 0; i