Leii

Radar Chart

A radar chart is a graphical method of displaying multivariate data in
the form of a two-dimensional chart of three or more quantitative
variables represented on axes starting from the same point.
@@ -18,3 +18,5 @@ @@ -18,3 +18,5 @@
18 #import "PNChartDelegate.h" 18 #import "PNChartDelegate.h"
19 #import "PNPieChart.h" 19 #import "PNPieChart.h"
20 #import "PNScatterChart.h" 20 #import "PNScatterChart.h"
  21 +#import "PNRadarChart.h"
  22 +#import "PNRadarChartDataItem.h"
  1 +//
  2 +// PNRadarChart.h
  3 +// PNChartDemo
  4 +//
  5 +// Created by Lei on 15/7/1.
  6 +// Copyright (c) 2015年 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +#import "PNGenericChart.h"
  11 +#import "PNRadarChartDataItem.h"
  12 +
  13 +#define MAXCIRCLE 20
  14 +
  15 +typedef NS_ENUM(NSUInteger, PNRadarChartLabelStyle) {
  16 + PNRadarChartLabelStyleCircle = 0,
  17 + PNRadarChartLabelStyleHorizontal,
  18 + PNRadarChartLabelStyleHidden,
  19 +};
  20 +
  21 +@interface PNRadarChart : PNGenericChart
  22 +
  23 +-(id)initWithFrame:(CGRect)frame items:(NSArray *)items valueDivider:(CGFloat)unitValue;
  24 +/**
  25 + *Draws the chart in an animated fashion.
  26 + */
  27 +-(void)strokeChart;
  28 +
  29 +/** Array of `RadarChartDataItem` objects, one for each corner. */
  30 +@property(nonatomic)NSArray *chartData;
  31 +/** The unit of this chart ,default is 1 */
  32 +@property(nonatomic)CGFloat valueDivider;
  33 +/** The maximum for the range of values to display on the chart */
  34 +@property(nonatomic)CGFloat maxValue;
  35 +/** Default is gray. */
  36 +@property(nonatomic)UIColor *webColor;
  37 +/** Default is green , with an alpha of 0.7 */
  38 +@property(nonatomic)UIColor *plotColor;
  39 +/** Default is black */
  40 +@property(nonatomic)UIColor *fontColor;
  41 +/** Default is orange */
  42 +@property(nonatomic)UIColor *graduationColor;
  43 +/** Default is 15 */
  44 +@property(nonatomic)CGFloat fontSize;
  45 +/** Controls the labels display style that around chart */
  46 +@property(nonatomic,assign)PNRadarChartLabelStyle labelStyle;
  47 +/** Tap the label will display detail value ,default is YES. */
  48 +@property(nonatomic,assign)BOOL isLabelTouchable;
  49 +/** is show graduation on the chart ,default is NO. */
  50 +@property(nonatomic,assign)BOOL isShowGraduation;
  51 +
  52 +@end
  1 +//
  2 +// PNRadarChart.m
  3 +// PNChartDemo
  4 +//
  5 +// Created by Lei on 15/7/1.
  6 +// Copyright (c) 2015年 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import "PNRadarChart.h"
  10 +
  11 +@interface PNRadarChart()
  12 +
  13 +@property(nonatomic)CGFloat centerX;
  14 +@property(nonatomic)CGFloat centerY;
  15 +@property(nonatomic)NSMutableArray *pointsToWebArrayArray;
  16 +@property(nonatomic)NSMutableArray *pointsToPlotArray;
  17 +@property(nonatomic)UILabel *detailLabel;
  18 +@property(nonatomic)CGFloat lengthUnit;
  19 +@property(nonatomic)CAShapeLayer *chartPlot;
  20 +
  21 +@end
  22 +
  23 +@implementation PNRadarChart
  24 +
  25 +-(id)initWithFrame:(CGRect)frame items:(NSArray *)items valueDivider:(CGFloat)unitValue{
  26 + self=[super initWithFrame:frame];
  27 + if (self) {
  28 + self.backgroundColor = [UIColor clearColor];
  29 + self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  30 +
  31 + //Public iVar
  32 + if ([items count]< 3) {
  33 + NSLog( @"At least three items!");
  34 + NSArray *defaultArray = @[[PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
  35 + [PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
  36 + [PNRadarChartDataItem dataItemWithValue:0 description:@"Default"],
  37 + ];
  38 + defaultArray = [defaultArray arrayByAddingObjectsFromArray:items];
  39 + _chartData = [NSArray arrayWithArray:defaultArray];
  40 + }else{
  41 + _chartData = [NSArray arrayWithArray:items];
  42 + }
  43 + _valueDivider = unitValue;
  44 + _maxValue = 1;
  45 + _webColor = [UIColor grayColor];
  46 + _plotColor = [UIColor colorWithRed:.4 green:.8 blue:.4 alpha:.7];
  47 + _fontColor = [UIColor blackColor];
  48 + _graduationColor = [UIColor orangeColor];
  49 + _fontSize = 15;
  50 + _labelStyle = PNRadarChartLabelStyleHorizontal;
  51 + _isLabelTouchable = YES;
  52 + _isShowGraduation = NO;
  53 +
  54 + //Private iVar
  55 + _centerX = frame.size.width/2;
  56 + _centerY = frame.size.height/2;
  57 + _pointsToWebArrayArray = [NSMutableArray array];
  58 + _pointsToPlotArray = [NSMutableArray array];
  59 + _lengthUnit = 0;
  60 + _chartPlot = [CAShapeLayer layer];
  61 + _chartPlot.lineCap = kCALineCapButt;
  62 + _chartPlot.fillColor = _plotColor.CGColor;
  63 + _chartPlot.lineWidth = 1.0;
  64 + [self.layer addSublayer:_chartPlot];
  65 + //init detailLabel
  66 + _detailLabel = [[UILabel alloc] init];
  67 + _detailLabel.backgroundColor = [UIColor colorWithRed:.9 green:.9 blue:.1 alpha:.9];
  68 + _detailLabel.textAlignment = NSTextAlignmentCenter;
  69 + _detailLabel.textColor = [UIColor colorWithWhite:1 alpha:1];
  70 + _detailLabel.font = [UIFont systemFontOfSize:15];
  71 + [_detailLabel setHidden:YES];
  72 + [self addSubview:_detailLabel];
  73 +
  74 + [self strokeChart];
  75 + }
  76 + return self;
  77 +}
  78 +
  79 +#pragma mark - main
  80 +-(void)calculateChartPoints{
  81 + [_pointsToPlotArray removeAllObjects];
  82 + [_pointsToWebArrayArray removeAllObjects];
  83 +
  84 + //init Descriptions , Values and Angles.
  85 + NSMutableArray *descriptions = [NSMutableArray array];
  86 + NSMutableArray *values = [NSMutableArray array];
  87 + NSMutableArray *angles = [NSMutableArray array];
  88 + for (int i=0;i<_chartData.count;i++) {
  89 + PNRadarChartDataItem *item = (PNRadarChartDataItem *)[_chartData objectAtIndex:i];
  90 + [descriptions addObject:item.textDescription];
  91 + [values addObject:[NSNumber numberWithFloat:item.value]];
  92 + CGFloat angleValue = (float)i/(float)[_chartData count]*2*M_PI;
  93 + [angles addObject:[NSNumber numberWithFloat:angleValue]];
  94 + }
  95 +
  96 + //calculate all the lengths
  97 + _maxValue = [self getMaxValueFromArray:values];
  98 + CGFloat margin = 0;
  99 + if (_labelStyle==PNRadarChartLabelStyleCircle) {
  100 + margin = MIN(_centerX , _centerY)*3/10;
  101 + }else if (_labelStyle==PNRadarChartLabelStyleHorizontal) {
  102 + margin = [self getMaxWidthLabelFromArray:descriptions withFontSize:_fontSize];
  103 + }
  104 + CGFloat maxLength = ceil(MIN(_centerX, _centerY) - margin);
  105 + int plotCircles = (_maxValue/_valueDivider);
  106 + if (plotCircles > MAXCIRCLE) {
  107 + NSLog(@"Circle number is higher than max");
  108 + plotCircles = MAXCIRCLE;
  109 + _valueDivider = _maxValue/plotCircles;
  110 + }
  111 + _lengthUnit = maxLength/plotCircles;
  112 + NSArray *lengthArray = [self getLengthArrayWithCircleNum:(int)plotCircles];
  113 +
  114 + //get all the points and plot
  115 + for (NSNumber *lengthNumber in lengthArray) {
  116 + CGFloat length = [lengthNumber floatValue];
  117 + [_pointsToWebArrayArray addObject:[self getWebPointWithLength:length angleArray:angles]];
  118 + }
  119 + int section = 0;
  120 + for (id value in values) {
  121 + CGFloat valueFloat = [value floatValue];
  122 + if (valueFloat>_maxValue) {
  123 + NSString *reason = [NSString stringWithFormat:@"Value number is higher than max -value: %f - maxValue: %f",valueFloat,_maxValue];
  124 + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil];
  125 + return;
  126 + }
  127 +
  128 + CGFloat length = valueFloat/_maxValue*maxLength;
  129 + CGFloat angle = [[angles objectAtIndex:section] floatValue];
  130 + CGFloat x = _centerX +length*cos(angle);
  131 + CGFloat y = _centerY +length*sin(angle);
  132 + NSValue* point = [NSValue valueWithCGPoint:CGPointMake(x, y)];
  133 + [_pointsToPlotArray addObject:point];
  134 + section++;
  135 + }
  136 + //set the labels
  137 + [self drawLabelWithMaxLength:maxLength labelArray:descriptions angleArray:angles];
  138 +
  139 + }
  140 +#pragma mark - Draw
  141 +
  142 +- (void)drawRect:(CGRect)rect {
  143 + // Drawing code
  144 + CGContextRef context = UIGraphicsGetCurrentContext();
  145 + CGContextClearRect(context, rect);
  146 + int section = 0;
  147 + //circles
  148 + for(NSArray *pointArray in _pointsToWebArrayArray){
  149 + //plot backgound
  150 + CGContextRef graphContext = UIGraphicsGetCurrentContext();
  151 + CGContextBeginPath(graphContext);
  152 + CGPoint beginPoint = [[pointArray objectAtIndex:0] CGPointValue];
  153 + CGContextMoveToPoint(graphContext, beginPoint.x, beginPoint.y);
  154 + for(NSValue* pointValue in pointArray){
  155 + CGPoint point = [pointValue CGPointValue];
  156 + CGContextAddLineToPoint(graphContext, point.x, point.y);
  157 + }
  158 + CGContextAddLineToPoint(graphContext, beginPoint.x, beginPoint.y);
  159 + CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor);
  160 + CGContextStrokePath(graphContext);
  161 +
  162 + }
  163 + //cuts
  164 + NSArray *largestPointArray = [_pointsToWebArrayArray lastObject];
  165 + for (NSValue *pointValue in largestPointArray){
  166 + section++;
  167 + if (section==1&&_isShowGraduation)continue;
  168 +
  169 + CGContextRef graphContext = UIGraphicsGetCurrentContext();
  170 + CGContextBeginPath(graphContext);
  171 + CGContextMoveToPoint(graphContext, _centerX, _centerY);
  172 + CGPoint point = [pointValue CGPointValue];
  173 + CGContextAddLineToPoint(graphContext, point.x, point.y);
  174 + CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor);
  175 + CGContextStrokePath(graphContext);
  176 + }
  177 +
  178 +
  179 +}
  180 +
  181 +-(void)strokeChart{
  182 +
  183 + [self calculateChartPoints];
  184 + [self setNeedsDisplay];
  185 + [_detailLabel setHidden:YES];
  186 +
  187 + //Draw plot
  188 + [_chartPlot removeAllAnimations];
  189 + UIBezierPath *plotline = [UIBezierPath bezierPath];
  190 + CGPoint beginPoint = [[_pointsToPlotArray objectAtIndex:0] CGPointValue];
  191 + [plotline moveToPoint:CGPointMake(beginPoint.x, beginPoint.y)];
  192 + for(NSValue *pointValue in _pointsToPlotArray){
  193 + CGPoint point = [pointValue CGPointValue];
  194 + [plotline addLineToPoint:CGPointMake(point.x ,point.y)];
  195 +
  196 + }
  197 + [plotline setLineWidth:1];
  198 + [plotline setLineCapStyle:kCGLineCapButt];
  199 +
  200 + _chartPlot.path = plotline.CGPath;
  201 +
  202 + CABasicAnimation *animateScale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
  203 + animateScale.fromValue = [NSNumber numberWithFloat:0.f];
  204 + animateScale.toValue = [NSNumber numberWithFloat:1.0f];
  205 +
  206 + CABasicAnimation *animateMove = [CABasicAnimation animationWithKeyPath:@"position"];
  207 + animateMove.fromValue = [NSValue valueWithCGPoint:CGPointMake(_centerX, _centerY)];
  208 + animateMove.toValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
  209 +
  210 + CABasicAnimation *animateAlpha = [CABasicAnimation animationWithKeyPath:@"opacity"];
  211 + animateAlpha.fromValue = [NSNumber numberWithFloat:0.f];
  212 +
  213 + CAAnimationGroup *aniGroup = [CAAnimationGroup animation];
  214 + aniGroup.duration = 1.f;
  215 + aniGroup.repeatCount = 1;
  216 + aniGroup.animations = [NSArray arrayWithObjects:animateScale,animateMove,animateAlpha, nil];
  217 + aniGroup.removedOnCompletion = YES;
  218 +
  219 + [_chartPlot addAnimation:aniGroup forKey:nil];
  220 +
  221 + [self showGraduation];
  222 +}
  223 +
  224 +#pragma mark - Helper
  225 +
  226 +-(void)drawLabelWithMaxLength:(CGFloat)maxLength labelArray:(NSArray *)labelArray angleArray:(NSArray *)angleArray{
  227 + //set labels
  228 + int labelTag = 121;
  229 + while (true) {
  230 + UIView *label = [self viewWithTag:labelTag];
  231 + if(!label)break;
  232 + [label removeFromSuperview];
  233 + }
  234 + int section = 0;
  235 + CGFloat labelLength = maxLength + maxLength/10;
  236 +
  237 + for (NSString *labelString in labelArray) {
  238 + CGFloat angle = [[angleArray objectAtIndex:section] floatValue];
  239 + CGFloat x = _centerX + labelLength *cos(angle);
  240 + CGFloat y = _centerY + labelLength *sin(angle);
  241 +
  242 + UILabel *label = [[UILabel alloc] init] ;
  243 + label.backgroundColor = [UIColor clearColor];
  244 + label.font = [UIFont systemFontOfSize:_fontSize];
  245 + label.text = labelString;
  246 + label.tag = labelTag;
  247 + CGSize detailSize = [labelString sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}];
  248 +
  249 + switch (_labelStyle) {
  250 + case PNRadarChartLabelStyleCircle:
  251 + label.frame = CGRectMake(x-5*_fontSize/2, y-_fontSize/2, 5*_fontSize, _fontSize);
  252 + label.transform = CGAffineTransformMakeRotation(((float)section/[labelArray count])*(2*M_PI)+M_PI_2);
  253 + label.textAlignment = NSTextAlignmentCenter;
  254 +
  255 + break;
  256 + case PNRadarChartLabelStyleHorizontal:
  257 + if (x<_centerX) {
  258 + label.frame = CGRectMake(x-detailSize.width, y-detailSize.height/2, detailSize.width, detailSize.height);
  259 + label.textAlignment = NSTextAlignmentRight;
  260 + }else{
  261 + label.frame = CGRectMake(x, y-detailSize.height/2, detailSize.width , detailSize.height);
  262 + label.textAlignment = NSTextAlignmentLeft;
  263 + }
  264 + break;
  265 + case PNRadarChartLabelStyleHidden:
  266 + [label setHidden:YES];
  267 + break;
  268 + default:
  269 + break;
  270 + }
  271 + [label sizeToFit];
  272 +
  273 + label.userInteractionEnabled = YES;
  274 + UITapGestureRecognizer *tapLabelGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapLabel:)];
  275 + [label addGestureRecognizer:tapLabelGesture];
  276 + [self addSubview:label];
  277 +
  278 + section ++;
  279 + }
  280 +
  281 +}
  282 +
  283 +-(void)tapLabel:(UITapGestureRecognizer *)recognizer{
  284 + UILabel *label=(UILabel*)recognizer.view;
  285 + _detailLabel.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y-30, 50, 25);
  286 + for (PNRadarChartDataItem *item in _chartData) {
  287 + if ([label.text isEqualToString:item.textDescription]) {
  288 + _detailLabel.text = [NSString stringWithFormat:@"%.2f", item.value];
  289 + break;
  290 + }
  291 + }
  292 + [_detailLabel setHidden:NO];
  293 +
  294 +}
  295 +
  296 +-(void)showGraduation{
  297 + int labelTag = 112;
  298 + while (true) {
  299 + UIView *label = [self viewWithTag:labelTag];
  300 + if(!label)break;
  301 + [label removeFromSuperview];
  302 + }
  303 + int section = 0;
  304 + for (NSArray *pointsArray in _pointsToWebArrayArray) {
  305 + section++;
  306 + CGPoint labelPoint = [[pointsArray objectAtIndex:0] CGPointValue];
  307 + UILabel *graduationLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelPoint.x-_lengthUnit, labelPoint.y-_lengthUnit*5/8, _lengthUnit*5/8, _lengthUnit)];
  308 + graduationLabel.adjustsFontSizeToFitWidth = YES;
  309 + graduationLabel.tag = labelTag;
  310 + graduationLabel.font = [UIFont systemFontOfSize:ceil(_lengthUnit)];
  311 + graduationLabel.textColor = [UIColor orangeColor];
  312 + graduationLabel.text = [NSString stringWithFormat:@"%.0f",_valueDivider*section];
  313 + [self addSubview:graduationLabel];
  314 + if (_isShowGraduation) {
  315 + [graduationLabel setHidden:NO];
  316 + }else{
  317 + [graduationLabel setHidden:YES];}
  318 + }
  319 +
  320 +}
  321 +
  322 +-(NSArray *)getWebPointWithLength:(CGFloat)length angleArray:(NSArray *)angleArray{
  323 + NSMutableArray *pointArray = [NSMutableArray array];
  324 + for (NSNumber *angleNumber in angleArray) {
  325 + CGFloat angle = [angleNumber floatValue];
  326 + CGFloat x = _centerX + length*cos(angle);
  327 + CGFloat y = _centerY + length*sin(angle);
  328 + [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(x,y)]];
  329 + }
  330 + return pointArray;
  331 +
  332 +}
  333 +
  334 +-(NSArray *)getLengthArrayWithCircleNum:(int)plotCircles{
  335 + NSMutableArray *lengthArray = [NSMutableArray array];
  336 + CGFloat length = 0;
  337 + for (int i = 0; i < plotCircles; i++) {
  338 + length += _lengthUnit;
  339 + [lengthArray addObject:[NSNumber numberWithFloat:length]];
  340 + }
  341 + return lengthArray;
  342 +}
  343 +
  344 +-(CGFloat)getMaxWidthLabelFromArray:(NSArray *)keyArray withFontSize:(CGFloat)size{
  345 + CGFloat maxWidth = 0;
  346 + for (NSString *str in keyArray) {
  347 + CGSize detailSize = [str sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}];
  348 + maxWidth = MAX(maxWidth, detailSize.width);
  349 + }
  350 + return maxWidth;
  351 +}
  352 +
  353 +-(CGFloat)getMaxValueFromArray:(NSArray *)valueArray{
  354 + CGFloat max = _maxValue;
  355 + for (NSNumber *valueNum in valueArray) {
  356 + CGFloat valueFloat = [valueNum floatValue];
  357 + max = MAX(valueFloat, max);
  358 + }
  359 + return ceil(max);
  360 +}
  361 +
  362 +
  363 +
  364 +@end
  1 +//
  2 +// PNRadarChartDataItem.h
  3 +// PNChartDemo
  4 +//
  5 +// Created by Lei on 15/7/1.
  6 +// Copyright (c) 2015年 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface PNRadarChartDataItem : NSObject
  12 +
  13 ++ (instancetype)dataItemWithValue:(CGFloat)value
  14 + description:(NSString *)description;
  15 +
  16 +@property (nonatomic) CGFloat value;
  17 +@property (nonatomic,copy) NSString *textDescription;
  18 +
  19 +@end
  1 +//
  2 +// PNRadarChartDataItem.m
  3 +// PNChartDemo
  4 +//
  5 +// Created by Lei on 15/7/1.
  6 +// Copyright (c) 2015年 kevinzhow. All rights reserved.
  7 +//
  8 +
  9 +#import "PNRadarChartDataItem.h"
  10 +
  11 +@implementation PNRadarChartDataItem
  12 +
  13 ++ (instancetype)dataItemWithValue:(CGFloat)value
  14 + description:(NSString *)description {
  15 + PNRadarChartDataItem *item = [PNRadarChartDataItem new];
  16 + item.value = value;
  17 + item.textDescription = description;
  18 + return item;
  19 +}
  20 +
  21 +- (void)setValue:(CGFloat)value{
  22 + if (value<0) {
  23 + _value = 0;
  24 + NSLog(@"Value value can not be negative");
  25 + }
  26 + _value = value;
  27 +}
  28 +
  29 +@end
@@ -35,6 +35,8 @@ @@ -35,6 +35,8 @@
35 9FE15DF8190BB014004129F5 /* PNChartLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FE15DE9190BB014004129F5 /* PNChartLabel.m */; }; 35 9FE15DF8190BB014004129F5 /* PNChartLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FE15DE9190BB014004129F5 /* PNChartLabel.m */; };
36 9FE15DFA190BB014004129F5 /* PNColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FE15DEE190BB014004129F5 /* PNColor.m */; }; 36 9FE15DFA190BB014004129F5 /* PNColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FE15DEE190BB014004129F5 /* PNColor.m */; };
37 A9C75FA61A9F1DA900A54638 /* PNGenericChart.m in Sources */ = {isa = PBXBuildFile; fileRef = A9C75FA51A9F1DA900A54638 /* PNGenericChart.m */; }; 37 A9C75FA61A9F1DA900A54638 /* PNGenericChart.m in Sources */ = {isa = PBXBuildFile; fileRef = A9C75FA51A9F1DA900A54638 /* PNGenericChart.m */; };
  38 + ABD79D021B43700800A7C300 /* PNRadarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = ABD79D011B43700800A7C300 /* PNRadarChart.m */; };
  39 + ABD79D051B43CF8000A7C300 /* PNRadarChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = ABD79D041B43CF8000A7C300 /* PNRadarChartDataItem.m */; };
38 E2C3ED5773A1409C8367CC70 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BA6321352024B1FBA0158B0 /* libPods.a */; }; 40 E2C3ED5773A1409C8367CC70 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BA6321352024B1FBA0158B0 /* libPods.a */; };
39 /* End PBXBuildFile section */ 41 /* End PBXBuildFile section */
40 42
@@ -103,6 +105,10 @@ @@ -103,6 +105,10 @@
103 9FE15DEE190BB014004129F5 /* PNColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNColor.m; sourceTree = "<group>"; }; 105 9FE15DEE190BB014004129F5 /* PNColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNColor.m; sourceTree = "<group>"; };
104 A9C75FA41A9F1DA900A54638 /* PNGenericChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNGenericChart.h; sourceTree = "<group>"; }; 106 A9C75FA41A9F1DA900A54638 /* PNGenericChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNGenericChart.h; sourceTree = "<group>"; };
105 A9C75FA51A9F1DA900A54638 /* PNGenericChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNGenericChart.m; sourceTree = "<group>"; }; 107 A9C75FA51A9F1DA900A54638 /* PNGenericChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNGenericChart.m; sourceTree = "<group>"; };
  108 + ABD79D001B43700800A7C300 /* PNRadarChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNRadarChart.h; sourceTree = "<group>"; };
  109 + ABD79D011B43700800A7C300 /* PNRadarChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNRadarChart.m; sourceTree = "<group>"; };
  110 + ABD79D031B43CF8000A7C300 /* PNRadarChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PNRadarChartDataItem.h; sourceTree = "<group>"; };
  111 + ABD79D041B43CF8000A7C300 /* PNRadarChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PNRadarChartDataItem.m; sourceTree = "<group>"; };
106 B0A0D7DDAB496680487BF1E5 /* libPods-PNChartTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PNChartTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 112 B0A0D7DDAB496680487BF1E5 /* libPods-PNChartTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PNChartTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
107 EFE4F6360943ED4001072124 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; }; 113 EFE4F6360943ED4001072124 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
108 FB2FFF68E5C9B426137EDD03 /* Pods-PNChartTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PNChartTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PNChartTests/Pods-PNChartTests.debug.xcconfig"; sourceTree = "<group>"; }; 114 FB2FFF68E5C9B426137EDD03 /* Pods-PNChartTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PNChartTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PNChartTests/Pods-PNChartTests.debug.xcconfig"; sourceTree = "<group>"; };
@@ -263,6 +269,10 @@ @@ -263,6 +269,10 @@
263 91177ED7198DFAC400017E27 /* PNPieChartDataItem.m */, 269 91177ED7198DFAC400017E27 /* PNPieChartDataItem.m */,
264 A9C75FA41A9F1DA900A54638 /* PNGenericChart.h */, 270 A9C75FA41A9F1DA900A54638 /* PNGenericChart.h */,
265 A9C75FA51A9F1DA900A54638 /* PNGenericChart.m */, 271 A9C75FA51A9F1DA900A54638 /* PNGenericChart.m */,
  272 + ABD79D001B43700800A7C300 /* PNRadarChart.h */,
  273 + ABD79D011B43700800A7C300 /* PNRadarChart.m */,
  274 + ABD79D031B43CF8000A7C300 /* PNRadarChartDataItem.h */,
  275 + ABD79D041B43CF8000A7C300 /* PNRadarChartDataItem.m */,
266 ); 276 );
267 path = PNChart; 277 path = PNChart;
268 sourceTree = "<group>"; 278 sourceTree = "<group>";
@@ -434,11 +444,13 @@ @@ -434,11 +444,13 @@
434 files = ( 444 files = (
435 91177EDE198DFAC400017E27 /* PNLineChart.m in Sources */, 445 91177EDE198DFAC400017E27 /* PNLineChart.m in Sources */,
436 9FE15DF8190BB014004129F5 /* PNChartLabel.m in Sources */, 446 9FE15DF8190BB014004129F5 /* PNChartLabel.m in Sources */,
  447 + ABD79D021B43700800A7C300 /* PNRadarChart.m in Sources */,
437 91177EDC198DFAC400017E27 /* PNCircleChart.m in Sources */, 448 91177EDC198DFAC400017E27 /* PNCircleChart.m in Sources */,
438 9FE15DFA190BB014004129F5 /* PNColor.m in Sources */, 449 9FE15DFA190BB014004129F5 /* PNColor.m in Sources */,
439 91177ED8198DFAC400017E27 /* PNBar.m in Sources */, 450 91177ED8198DFAC400017E27 /* PNBar.m in Sources */,
440 91177EE2198DFAC400017E27 /* PNLineChartDataItem.m in Sources */, 451 91177EE2198DFAC400017E27 /* PNLineChartDataItem.m in Sources */,
441 0AF7A8AF182AAEEF003645C4 /* PCChartViewController.m in Sources */, 452 0AF7A8AF182AAEEF003645C4 /* PCChartViewController.m in Sources */,
  453 + ABD79D051B43CF8000A7C300 /* PNRadarChartDataItem.m in Sources */,
442 0A29228A1A423FB300A42BC4 /* PNScatterChartDataItem.m in Sources */, 454 0A29228A1A423FB300A42BC4 /* PNScatterChartDataItem.m in Sources */,
443 A9C75FA61A9F1DA900A54638 /* PNGenericChart.m in Sources */, 455 A9C75FA61A9F1DA900A54638 /* PNGenericChart.m in Sources */,
444 91177EE6198DFAC400017E27 /* PNPieChartDataItem.m in Sources */, 456 91177EE6198DFAC400017E27 /* PNPieChartDataItem.m in Sources */,
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="9Rt-UT-IxH"> 2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7531" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="9Rt-UT-IxH">
3 <dependencies> 3 <dependencies>
4 <deployment identifier="iOS"/> 4 <deployment identifier="iOS"/>
5 - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/> 5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7520"/>
6 </dependencies> 6 </dependencies>
7 <scenes> 7 <scenes>
8 <!--PNChart--> 8 <!--PNChart-->
@@ -45,13 +45,13 @@ @@ -45,13 +45,13 @@
45 </connections> 45 </connections>
46 </switch> 46 </switch>
47 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Percentage" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IKu-qh-ksi"> 47 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Percentage" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IKu-qh-ksi">
48 - <rect key="frame" x="16" y="528" width="88" height="21"/> 48 + <rect key="frame" x="16" y="528" width="121" height="21"/>
49 <fontDescription key="fontDescription" type="system" pointSize="17"/> 49 <fontDescription key="fontDescription" type="system" pointSize="17"/>
50 <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> 50 <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
51 <nil key="highlightedColor"/> 51 <nil key="highlightedColor"/>
52 </label> 52 </label>
53 - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Show Labels" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ifm-a9-Wkq"> 53 + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Show Labels" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ifm-a9-Wkq">
54 - <rect key="frame" x="211" y="527" width="99" height="21"/> 54 + <rect key="frame" x="192" y="527" width="118" height="21"/>
55 <fontDescription key="fontDescription" type="system" pointSize="17"/> 55 <fontDescription key="fontDescription" type="system" pointSize="17"/>
56 <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> 56 <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
57 <nil key="highlightedColor"/> 57 <nil key="highlightedColor"/>
@@ -188,6 +188,26 @@ @@ -188,6 +188,26 @@
188 <segue destination="Tha-Wr-sPW" kind="push" identifier="scatterChart" id="V7s-JV-4Nx"/> 188 <segue destination="Tha-Wr-sPW" kind="push" identifier="scatterChart" id="V7s-JV-4Nx"/>
189 </connections> 189 </connections>
190 </tableViewCell> 190 </tableViewCell>
  191 + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" textLabel="Sjk-AS-XhW" style="IBUITableViewCellStyleDefault" id="bev-fA-J4Q">
  192 + <rect key="frame" x="0.0" y="196" width="320" height="44"/>
  193 + <autoresizingMask key="autoresizingMask"/>
  194 + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bev-fA-J4Q" id="nSV-Wu-TAu">
  195 + <rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
  196 + <autoresizingMask key="autoresizingMask"/>
  197 + <subviews>
  198 + <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="RadarChart" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Sjk-AS-XhW">
  199 + <rect key="frame" x="15" y="0.0" width="270" height="43"/>
  200 + <autoresizingMask key="autoresizingMask"/>
  201 + <fontDescription key="fontDescription" type="system" pointSize="18"/>
  202 + <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
  203 + <nil key="highlightedColor"/>
  204 + </label>
  205 + </subviews>
  206 + </tableViewCellContentView>
  207 + <connections>
  208 + <segue destination="Tha-Wr-sPW" kind="push" identifier="radarChart" id="4D9-t3-nzn"/>
  209 + </connections>
  210 + </tableViewCell>
191 </cells> 211 </cells>
192 </tableViewSection> 212 </tableViewSection>
193 </sections> 213 </sections>
@@ -220,6 +240,6 @@ @@ -220,6 +240,6 @@
220 <simulatedScreenMetrics key="destination" type="retina4"/> 240 <simulatedScreenMetrics key="destination" type="retina4"/>
221 </simulatedMetricsContainer> 241 </simulatedMetricsContainer>
222 <inferredMetricsTieBreakers> 242 <inferredMetricsTieBreakers>
223 - <segue reference="V7s-JV-4Nx"/> 243 + <segue reference="pvQ-oy-a9a"/>
224 </inferredMetricsTieBreakers> 244 </inferredMetricsTieBreakers>
225 </document> 245 </document>
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 @property (nonatomic) PNCircleChart * circleChart; 17 @property (nonatomic) PNCircleChart * circleChart;
18 @property (nonatomic) PNPieChart *pieChart; 18 @property (nonatomic) PNPieChart *pieChart;
19 @property (nonatomic) PNScatterChart *scatterChart; 19 @property (nonatomic) PNScatterChart *scatterChart;
  20 +@property (nonatomic) PNRadarChart *radarChart;
20 21
21 @property (weak, nonatomic) IBOutlet UILabel *titleLabel; 22 @property (weak, nonatomic) IBOutlet UILabel *titleLabel;
22 23
@@ -206,6 +206,29 @@ @@ -206,6 +206,29 @@
206 self.changeValueButton.hidden = YES; 206 self.changeValueButton.hidden = YES;
207 [self.view addSubview:self.scatterChart]; 207 [self.view addSubview:self.scatterChart];
208 } 208 }
  209 + else if ([self.title isEqualToString:@"Radar Chart"])
  210 + {
  211 + self.titleLabel.text = @"Radar Chart";
  212 +
  213 + self.leftSwitch.hidden = NO;
  214 + self.rightSwitch.hidden = NO;
  215 + self.leftLabel.hidden = NO;
  216 + self.rightLabel.hidden = NO;
  217 + self.leftLabel.text = @"Labels Style";
  218 + self.rightLabel.text = @"Graduation";
  219 +
  220 + NSArray *items = @[[PNRadarChartDataItem dataItemWithValue:3 description:@"Art"],
  221 + [PNRadarChartDataItem dataItemWithValue:2 description:@"Math"],
  222 + [PNRadarChartDataItem dataItemWithValue:8 description:@"Sports"],
  223 + [PNRadarChartDataItem dataItemWithValue:5 description:@"Literature"],
  224 + [PNRadarChartDataItem dataItemWithValue:4 description:@"Other"],
  225 + ];
  226 + self.radarChart = [[PNRadarChart alloc] initWithFrame:CGRectMake(0, 135.0, SCREEN_WIDTH, 300.0) items:items valueDivider:1];
  227 + [self.radarChart strokeChart];
  228 +
  229 + [self.view addSubview:self.radarChart];
  230 + }
  231 +
209 } 232 }
210 233
211 234
@@ -310,6 +333,15 @@ @@ -310,6 +333,15 @@
310 } 333 }
311 [self.pieChart strokeChart]; 334 [self.pieChart strokeChart];
312 } 335 }
  336 + if ([self.title isEqualToString:@"Radar Chart"]){
  337 + UISwitch *showLabels = (UISwitch*) sender;
  338 + if (showLabels.on) {
  339 + self.radarChart.isShowGraduation = NO;
  340 + }else{
  341 + self.radarChart.isShowGraduation = YES;
  342 + }
  343 + [self.radarChart strokeChart];
  344 + }
313 } 345 }
314 346
315 - (IBAction)leftSwitchChanged:(id)sender { 347 - (IBAction)leftSwitchChanged:(id)sender {
@@ -322,5 +354,14 @@ @@ -322,5 +354,14 @@
322 } 354 }
323 [self.pieChart strokeChart]; 355 [self.pieChart strokeChart];
324 } 356 }
  357 + if ([self.title isEqualToString:@"Radar Chart"]){
  358 + UISwitch *showRelative = (UISwitch*) sender;
  359 + if (showRelative.on) {
  360 + self.radarChart.labelStyle = PNRadarChartLabelStyleHorizontal;
  361 + }else{
  362 + self.radarChart.labelStyle = PNRadarChartLabelStyleCircle;
  363 + }
  364 + [self.radarChart strokeChart];
  365 + }
325 } 366 }
326 @end 367 @end
@@ -45,6 +45,11 @@ @@ -45,6 +45,11 @@
45 //Add scatter chart 45 //Add scatter chart
46 46
47 viewController.title = @"Scatter Chart"; 47 viewController.title = @"Scatter Chart";
  48 + }else if ([segue.identifier isEqualToString:@"radarChart"])
  49 + {
  50 + //Add radar chart
  51 +
  52 + viewController.title = @"Radar Chart";
48 } 53 }
49 } 54 }
50 55