四维雷达图,A,B,C分级。
demo下载地址
BGRadarChartView.h
#import <UIKit/UIKit.h> @interface BGRadarChartView : UIView @property (nonatomic, strong) NSMutableArray *scoresArray; -(instancetype)initWithFrame:(CGRect)frame scoresArray:(NSMutableArray *)scoresArray; @end
BGRadarChartView.m
#import "BGRadarChartView.h" #import "UIColor+custom.h" #import "UIBezierPath+Pentagon.h" //#define kRScrollAlertViewWidth 590/2.0 #define kLabWidth 74 #define kMinLength 23 #define kInterval 7 @interface BGRadarChartView () @property (nonatomic, assign) CGPoint picCenter; @end @implementation BGRadarChartView -(instancetype)initWithFrame:(CGRect)frame scoresArray:(NSMutableArray *)scoresArray { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor colorWithHex:0xFFFFFF]; _scoresArray = [NSMutableArray array]; [self drawBgPentagon]; self.scoresArray = scoresArray; } return self; } - (void)setScoresArray:(NSMutableArray *)scoresArray { [_scoresArray removeAllObjects]; if(!scoresArray || ![scoresArray isKindOfClass:[NSArray class]] || scoresArray.count == 0) { return; } NSUInteger count = scoresArray.count; for(int i = 0; i < 4; i++) { if(i >= count) { [_scoresArray addObject:@"C"]; } else { NSString *str = scoresArray[i]; if(!isRadarEmptyString(str)) { if([str isEqualToString:@"A"] || [str isEqualToString:@"B"] || [str isEqualToString:@"C"]) { [_scoresArray addObject:str]; } else { [_scoresArray addObject:@"C"]; } } else { [_scoresArray addObject:@"C"]; } } } CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.backgroundColor = [UIColor clearColor].CGColor; shapeLayer.strokeColor = [UIColor colorWithHex:0x75C995 alpha:1.0].CGColor; UIColor *fillColor = [UIColor colorWithHex:0x75C995 alpha:1.0]; shapeLayer.fillColor = fillColor.CGColor; shapeLayer.path = [UIBezierPath drawRadarChartWithCenter:self.picCenter minLength:kMinLength/sqrt(2) scoresArray:_scoresArray]; [self.layer addSublayer:shapeLayer]; } #pragma mark - 描绘背景五边行 按等比放大 - (void)drawBgPentagon { NSArray *radiusArr = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%d", kMinLength], [NSString stringWithFormat:@"%d", kMinLength*2], [NSString stringWithFormat:@"%d", kMinLength*3],nil]; self.picCenter = CGPointMake(self.center.x-self.frame.origin.x,self.center.y-self.frame.origin.y); for (int i = 0; i < radiusArr.count; i++) { CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.backgroundColor = [UIColor clearColor].CGColor; shapeLayer.strokeColor = [UIColor colorWithHex:0x75C995 alpha:1.0].CGColor; shapeLayer.lineWidth = 1; // UIColor *fillColor = [colors objectAtIndex:i]; shapeLayer.fillColor = [UIColor colorWithHex:0xCEF9DE alpha:0.2].CGColor; shapeLayer.path = [UIBezierPath drawPentagonWithCenter:self.picCenter Length:[radiusArr[i] doubleValue]]; [self.layer addSublayer:shapeLayer]; } // CGPoint picCenter = CGPointMake(kRScrollAlertViewWidth / 2.0, 100.0); NSArray *titleArray = [NSArray arrayWithObjects:@"语言交流",@"个人情感发展",@"身体运动",@"探索与操作", nil]; NSArray *centerArray = [NSArray arrayWithObjects: [NSValue valueWithCGPoint:CGPointMake(self.picCenter.x - kLabWidth/2 - kMinLength*3* cos(M_PI / 4.0)-kInterval,self.picCenter.y)], [NSValue valueWithCGPoint:CGPointMake(self.picCenter.x ,self.picCenter.y - kMinLength*3 * sin(M_PI / 4.0)-kInterval -6)], [NSValue valueWithCGPoint:CGPointMake(self.picCenter.x + kMinLength*3 * cos(M_PI / 4.0) +kInterval+kLabWidth/2,self.picCenter.y)], [NSValue valueWithCGPoint:CGPointMake(self.picCenter.x,self.picCenter.y +kMinLength*3 * sin(M_PI / 4.0) +kInterval+6)],nil]; for (int i = 0; i < [titleArray count]; i++) { UILabel *lab = [self createLab]; lab.center = [[centerArray objectAtIndex:i] CGPointValue]; lab.text = titleArray[i]; if(0 == i) { lab.textAlignment = NSTextAlignmentRight; } else if(2 == i) { lab.textAlignment = NSTextAlignmentLeft; } [self addSubview:lab]; } } - (void)drawRect:(CGRect)rect { [self drawLineWithCenter:self.picCenter endPoint:CGPointMake(self.picCenter.x - kMinLength*3* cos(M_PI / 4.0),self.picCenter.y)]; [self drawLineWithCenter:self.picCenter endPoint:CGPointMake(self.picCenter.x ,self.picCenter.y - kMinLength*3 * sin(M_PI / 4.0))]; [self drawLineWithCenter:self.picCenter endPoint:CGPointMake(self.picCenter.x + kMinLength*3 * cos(M_PI / 4.0),self.picCenter.y)]; [self drawLineWithCenter:self.picCenter endPoint:CGPointMake(self.picCenter.x,self.picCenter.y +kMinLength*3 * sin(M_PI / 4.0))]; } - (void)drawLineWithCenter:(CGPoint)picCenter endPoint:(CGPoint)endPoint { //1 获取当前的绘制图形上下文 CGContextRef context = UIGraphicsGetCurrentContext(); //2 创建并且设置路径 可变路径 CGMutablePathRef path = CGPathCreateMutable(); //设置路径上的点 //路径的起始点 //path 需要添加起始点的可变路径 //transform 坐标系变化 CGPathMoveToPoint(path, NULL, picCenter.x, picCenter.y); //向路径中添加点 CGPathAddLineToPoint(path, NULL, endPoint.x, endPoint.y); //封闭路径 将路径的终点和起始点链接 CGPathCloseSubpath(path); //3 设置绘制属性 (线条颜色,线条粗细) //设置线段颜色 CGContextSetStrokeColorWithColor(context, [UIColor colorWithHex:0x75C995 alpha:1.0].CGColor); //设置图形的填充颜色 CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor); //设置线条宽度 CGContextSetLineWidth(context, 1); //设置线段连接点的样式 CGContextSetLineJoin(context, kCGLineJoinRound); //4 绘制路径 //将创建好的路径 添加到上下文中 CGContextAddPath(context, path); //在图形上下文中绘制已添加路径 //mode 绘制模式 CGContextDrawPath(context, kCGPathFillStroke); //在CG框架中 所有使用到了create函数创建的变量,都需要手动销毁 CGPathRelease(path); } -(UILabel *)createLab { UILabel *label = [[UILabel alloc] init]; label.textColor = [UIColor colorWithHex:0x333333]; label.textAlignment = NSTextAlignmentCenter; label.bounds = CGRectMake(0, 0, kLabWidth , 12); // label.picCenter = [[centerArray objectAtIndex:i] CGPointValue]; label.font = [UIFont systemFontOfSize:12]; // label.text = [titleArray objectAtIndex:i]; return label; }
UIBezierPath+Pentagon.h
#import <UIKit/UIKit.h> //判断字符串是否为空 #define isRadarEmptyString(str) ([str isKindOfClass:[NSNull class]] || str == nil || ![str isKindOfClass:[NSString class]] || [str length] < 1) //判断数组是否为空 #define isRadarEmptyArray(array) (array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0) @interface UIBezierPath (Pentagon) + (CGPathRef)drawPentagonWithCenter:(CGPoint)center LengthArray:(NSArray *)lengths; + (CGPathRef)drawPentagonWithCenter:(CGPoint)center Length:(double)length; + (NSArray *)converCoordinateFromLength:(NSArray *)lengthArray Center:(CGPoint)center; + (CGPathRef)drawRadarChartWithCenter:(CGPoint)center minLength:(double)minLength scoresArray:(NSMutableArray *)scoresArray; @end
UIBezierPath+Pentagon.m
#import "UIBezierPath+Pentagon.h" @implementation UIBezierPath (Pentagon) + (CGPathRef)drawRadarChartWithCenter:(CGPoint)center minLength:(double)minLength scoresArray:(NSMutableArray *)scoresArray { if(minLength <= 0 || isRadarEmptyArray(scoresArray) || scoresArray.count != 4) { return nil; } // NSMutableArray *lengthArray = [NSArray arrayWithObjects:@(length),@(length),@(length),@(length), nil]; NSMutableArray *coordinateArray = [NSMutableArray array]; NSString *score1 = scoresArray[0]; NSString *score2 = scoresArray[1]; NSString *score3 = scoresArray[2]; NSString *score4 = scoresArray[3]; CGFloat cx1 = center.x - ([score1 isEqualToString:@"A"] ? 3*minLength : ([score1 isEqualToString:@"B"] ? 2*minLength : minLength)); CGFloat cy1 = center.y; CGPoint point1 = CGPointMake(cx1,cy1); [coordinateArray addObject:[NSValue valueWithCGPoint:point1]]; CGFloat cx2 = center.x; CGFloat cy2 = center.y - ([score2 isEqualToString:@"A"] ? 3*minLength : ([score2 isEqualToString:@"B"] ? 2*minLength : minLength)); CGPoint point2 = CGPointMake(cx2, (cy2)); [coordinateArray addObject:[NSValue valueWithCGPoint:point2]]; CGFloat cx3 = center.x + ([score3 isEqualToString:@"A"] ? 3*minLength : ([score3 isEqualToString:@"B"] ? 2*minLength : minLength)); CGFloat cy3 = center.y; CGPoint point3 = CGPointMake(cx3,cy3); [coordinateArray addObject:[NSValue valueWithCGPoint:point3]]; CGFloat cx4 = center.x; CGFloat cy4 = center.y + ([score4 isEqualToString:@"A"] ? 3*minLength : ([score4 isEqualToString:@"B"] ? 2*minLength : minLength)); CGPoint point4 = CGPointMake(cx4, (cy4)); [coordinateArray addObject:[NSValue valueWithCGPoint:point4]]; UIBezierPath *bezierPath = [UIBezierPath bezierPath]; for (int i = 0; i < [coordinateArray count]; i++) { CGPoint point = [[coordinateArray objectAtIndex:i] CGPointValue]; if (i == 0) { [bezierPath moveToPoint:point]; } else { [bezierPath addLineToPoint:point]; } } [bezierPath closePath]; return bezierPath.CGPath; } + (CGPathRef)drawPentagonWithCenter:(CGPoint)center Length:(double)length { NSArray *lengths = [NSArray arrayWithObjects:@(length),@(length),@(length),@(length), nil]; return [self drawPentagonWithCenter:center LengthArray:lengths]; } + (CGPathRef)drawPentagonWithCenter:(CGPoint)center LengthArray:(NSArray *)lengths { NSArray *coordinates = [self converCoordinateFromLength:lengths Center:center]; UIBezierPath *bezierPath = [UIBezierPath bezierPath]; for (int i = 0; i < [coordinates count]; i++) { CGPoint point = [[coordinates objectAtIndex:i] CGPointValue]; if (i == 0) { [bezierPath moveToPoint:point]; } else { [bezierPath addLineToPoint:point]; } } [bezierPath closePath]; return bezierPath.CGPath; } + (NSArray *)converCoordinateFromLength:(NSArray *)lengthArray Center:(CGPoint)center { NSMutableArray *coordinateArray = [NSMutableArray array]; for (int i = 0; i < [lengthArray count] ; i++) { double length = [[lengthArray objectAtIndex:i] doubleValue]; CGPoint point = CGPointZero; if (i == 0) { point = CGPointMake(center.x - length * cos(M_PI / 4.0), center.y); } else if (i == 1) { point = CGPointMake(center.x, center.y - length * sin(M_PI / 4.0)); } else if (i == 2) { point = CGPointMake(center.x + length * cos(M_PI / 4.0), center.y); } else if (i == 3) { point = CGPointMake(center.x, center.y +length * sin(M_PI / 4.0)); } else { point = CGPointMake(center.x - length * cos(M_PI / 10.0), center.y + length * sin(M_PI / 10.0)); } [coordinateArray addObject:[NSValue valueWithCGPoint:point]]; } return coordinateArray; } @end
调用代码
#import "ViewController.h" #import "BGRadarChartView.h" #import "math.h" @interface ViewController () @property (nonatomic, strong) BGRadarChartView *chartV; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.chartV.center = self.view.center; [self.view addSubview:self.chartV]; } -(BGRadarChartView *)chartV { if (!_chartV) { _chartV = [[BGRadarChartView alloc] initWithFrame:CGRectMake(15, 100, 230, 320- 30) scoresArray:[NSMutableArray arrayWithObjects:@"A",@"C",@"C",@"C", nil]]; } return _chartV; } @end
UIColor+custom.h
#import <UIKit/UIKit.h> @interface UIColor (custom) + (UIColor *)colorWithHex:(int)hex; + (UIColor *)colorWithHex:(int)hex alpha:(CGFloat)alpha; @end
UIColor+custom.m
#import "UIColor+custom.h" @implementation UIColor (custom) + (UIColor *)colorWithHex:(int)hex { return [UIColor colorWithHex:hex alpha:1.0f]; } + (UIColor *)colorWithHex:(int)hex alpha:(CGFloat)alpha { return [UIColor colorWithRed:((float)((hex & 0xFF0000) >> 16))/255.0 green:((float)((hex & 0xFF00) >> 8))/255.0 blue:((float)(hex & 0xFF))/255.0 alpha:alpha]; }