removed defines from PNLineChart.h (not typesafe)
fixed issue #24
Showing
2 changed files
with
87 additions
and
56 deletions
| @@ -11,9 +11,8 @@ | @@ -11,9 +11,8 @@ | ||
| 11 | #import <QuartzCore/QuartzCore.h> | 11 | #import <QuartzCore/QuartzCore.h> |
| 12 | #import "PNChartDelegate.h" | 12 | #import "PNChartDelegate.h" |
| 13 | 13 | ||
| 14 | -#define chartMargin 10 | 14 | + |
| 15 | -#define yLabelMargin 15 | 15 | + |
| 16 | -#define yLabelHeight 11 | ||
| 17 | 16 | ||
| 18 | @interface PNLineChart : UIView | 17 | @interface PNLineChart : UIView |
| 19 | 18 | ||
| @@ -30,19 +29,31 @@ | @@ -30,19 +29,31 @@ | ||
| 30 | @property (strong, nonatomic) NSArray * yLabels; | 29 | @property (strong, nonatomic) NSArray * yLabels; |
| 31 | 30 | ||
| 32 | /** | 31 | /** |
| 33 | -* Array of `LineChartData` objects, one for each line. | 32 | + * Array of `LineChartData` objects, one for each line. |
| 34 | -*/ | 33 | + */ |
| 35 | @property (strong, nonatomic) NSArray *chartData; | 34 | @property (strong, nonatomic) NSArray *chartData; |
| 36 | 35 | ||
| 37 | @property (strong, nonatomic) NSMutableArray * pathPoints; | 36 | @property (strong, nonatomic) NSMutableArray * pathPoints; |
| 38 | 37 | ||
| 39 | @property (nonatomic) CGFloat xLabelWidth; | 38 | @property (nonatomic) CGFloat xLabelWidth; |
| 40 | 39 | ||
| 41 | -@property (nonatomic) float yValueMax; | 40 | +@property (nonatomic) CGFloat xLabelHeight; |
| 41 | + | ||
| 42 | +@property (nonatomic) CGFloat yValueMax; | ||
| 43 | + | ||
| 44 | +@property (nonatomic) CGFloat yValueMin; | ||
| 45 | + | ||
| 46 | +@property (nonatomic) NSInteger yLabelNum; | ||
| 47 | + | ||
| 48 | +@property (nonatomic) CGFloat yLabelHeight; | ||
| 49 | + | ||
| 50 | +@property (nonatomic) CGFloat chartCavanHeight; | ||
| 51 | + | ||
| 52 | +@property (nonatomic) CGFloat chartCavanWidth; | ||
| 53 | + | ||
| 54 | +@property (nonatomic) CGFloat chartMargin; | ||
| 42 | 55 | ||
| 43 | -@property (nonatomic) float chartCavanHeight; | ||
| 44 | 56 | ||
| 45 | -@property (nonatomic) float xLabelHeight; | ||
| 46 | 57 | ||
| 47 | @property (nonatomic) BOOL showLabel; | 58 | @property (nonatomic) BOOL showLabel; |
| 48 | 59 |
| @@ -54,21 +54,22 @@ | @@ -54,21 +54,22 @@ | ||
| 54 | 54 | ||
| 55 | -(void)setYLabels:(NSArray *)yLabels | 55 | -(void)setYLabels:(NSArray *)yLabels |
| 56 | { | 56 | { |
| 57 | - | 57 | + |
| 58 | - float level = _yValueMax / 5.0; | 58 | + float yStep = (_yValueMax-_yValueMin) / _yLabelNum; |
| 59 | - | 59 | + CGFloat yStepHeight = _chartCavanHeight / _yLabelNum; |
| 60 | + | ||
| 61 | + | ||
| 60 | NSInteger index = 0; | 62 | NSInteger index = 0; |
| 61 | - NSInteger num = [yLabels count] + 1; | 63 | + NSInteger num = _yLabelNum+1; |
| 62 | while (num > 0) { | 64 | while (num > 0) { |
| 63 | - CGFloat levelHeight = _chartCavanHeight /5.0; | 65 | + PNChartLabel * label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (_chartCavanHeight - index * yStepHeight), _chartMargin, _yLabelHeight)]; |
| 64 | - PNChartLabel * label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0,_chartCavanHeight - index * levelHeight + (levelHeight - yLabelHeight) , 20.0, yLabelHeight)]; | ||
| 65 | [label setTextAlignment:NSTextAlignmentRight]; | 66 | [label setTextAlignment:NSTextAlignmentRight]; |
| 66 | - label.text = [NSString stringWithFormat:@"%1.f",level * index]; | 67 | + label.text = [NSString stringWithFormat:@"%1.f",_yValueMin + (yStep * index)]; |
| 67 | [self addSubview:label]; | 68 | [self addSubview:label]; |
| 68 | index +=1 ; | 69 | index +=1 ; |
| 69 | num -= 1; | 70 | num -= 1; |
| 70 | } | 71 | } |
| 71 | - | 72 | + |
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | -(void)setXLabels:(NSArray *)xLabels | 75 | -(void)setXLabels:(NSArray *)xLabels |
| @@ -76,12 +77,12 @@ | @@ -76,12 +77,12 @@ | ||
| 76 | _xLabels = xLabels; | 77 | _xLabels = xLabels; |
| 77 | 78 | ||
| 78 | if(_showLabel){ | 79 | if(_showLabel){ |
| 79 | - _xLabelWidth = (self.frame.size.width - chartMargin - 30.0)/[xLabels count]; | 80 | + _xLabelWidth = _chartCavanWidth/[xLabels count]; |
| 80 | 81 | ||
| 81 | for(int index = 0; index < xLabels.count; index++) | 82 | for(int index = 0; index < xLabels.count; index++) |
| 82 | { | 83 | { |
| 83 | NSString* labelText = xLabels[index]; | 84 | NSString* labelText = xLabels[index]; |
| 84 | - PNChartLabel * label = [[PNChartLabel alloc] initWithFrame:CGRectMake(index * _xLabelWidth + 30.0, self.frame.size.height - 30.0, _xLabelWidth, 20.0)]; | 85 | + PNChartLabel * label = [[PNChartLabel alloc] initWithFrame:CGRectMake(2*_chartMargin + (index * _xLabelWidth) - (_xLabelWidth / 2), _chartMargin + _chartCavanHeight, _xLabelWidth, _chartMargin)]; |
| 85 | [label setTextAlignment:NSTextAlignmentCenter]; | 86 | [label setTextAlignment:NSTextAlignmentCenter]; |
| 86 | label.text = labelText; | 87 | label.text = labelText; |
| 87 | [self addSubview:label]; | 88 | [self addSubview:label]; |
| @@ -137,44 +138,47 @@ | @@ -137,44 +138,47 @@ | ||
| 137 | for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) { | 138 | for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) { |
| 138 | PNLineChartData *chartData = self.chartData[lineIndex]; | 139 | PNLineChartData *chartData = self.chartData[lineIndex]; |
| 139 | CAShapeLayer *chartLine = (CAShapeLayer *) self.chartLineArray[lineIndex]; | 140 | CAShapeLayer *chartLine = (CAShapeLayer *) self.chartLineArray[lineIndex]; |
| 140 | - | 141 | + |
| 141 | UIGraphicsBeginImageContext(self.frame.size); | 142 | UIGraphicsBeginImageContext(self.frame.size); |
| 142 | UIBezierPath * progressline = [UIBezierPath bezierPath]; | 143 | UIBezierPath * progressline = [UIBezierPath bezierPath]; |
| 143 | [_chartPath addObject:progressline]; | 144 | [_chartPath addObject:progressline]; |
| 144 | 145 | ||
| 145 | - PNLineChartDataItem *firstDataItem = chartData.getData(0); | 146 | + CGFloat xPosition = _chartMargin; |
| 146 | - CGFloat firstValue = firstDataItem.y; | 147 | + |
| 147 | - | ||
| 148 | - CGFloat xPosition = _xLabelWidth; | ||
| 149 | - | ||
| 150 | if(!_showLabel){ | 148 | if(!_showLabel){ |
| 151 | - _chartCavanHeight = self.frame.size.height - _xLabelHeight*2; | 149 | + //heuristic don't know why |
| 150 | + _yLabelHeight = 2; | ||
| 151 | + _chartCavanHeight = self.frame.size.height - 2*_yLabelHeight; | ||
| 152 | + _chartCavanWidth = self.frame.size.width; | ||
| 153 | + _yLabelHeight = 5.0; | ||
| 154 | + _chartMargin = 0.0; | ||
| 155 | + _xLabelWidth = (_chartCavanWidth / ([_xLabels count] -1)); | ||
| 152 | xPosition = 0; | 156 | xPosition = 0; |
| 153 | } | 157 | } |
| 154 | - | 158 | + |
| 155 | - CGFloat grade = (float)firstValue / _yValueMax; | ||
| 156 | NSMutableArray * linePointsArray = [[NSMutableArray alloc] init]; | 159 | NSMutableArray * linePointsArray = [[NSMutableArray alloc] init]; |
| 157 | - [progressline moveToPoint:CGPointMake( xPosition, _chartCavanHeight - grade * _chartCavanHeight + _xLabelHeight)]; | ||
| 158 | - [linePointsArray addObject:[NSValue valueWithCGPoint:CGPointMake( xPosition, _chartCavanHeight - grade * _chartCavanHeight + _xLabelHeight)]]; | ||
| 159 | [progressline setLineWidth:3.0]; | 160 | [progressline setLineWidth:3.0]; |
| 160 | [progressline setLineCapStyle:kCGLineCapRound]; | 161 | [progressline setLineCapStyle:kCGLineCapRound]; |
| 161 | [progressline setLineJoinStyle:kCGLineJoinRound]; | 162 | [progressline setLineJoinStyle:kCGLineJoinRound]; |
| 162 | - | ||
| 163 | 163 | ||
| 164 | - NSInteger index = 0; | 164 | + PNLineChartDataItem *dataItem; |
| 165 | + | ||
| 166 | + | ||
| 165 | for (NSUInteger i = 0; i < chartData.itemCount; i++) { | 167 | for (NSUInteger i = 0; i < chartData.itemCount; i++) { |
| 166 | - | 168 | + |
| 167 | - PNLineChartDataItem *dataItem = chartData.getData(i); | 169 | + dataItem = chartData.getData(i); |
| 168 | float value = dataItem.y; | 170 | float value = dataItem.y; |
| 169 | - | 171 | + |
| 170 | - CGFloat innerGrade = value / _yValueMax; | 172 | + CGFloat innerGrade = (value - _yValueMin) / ( _yValueMax - _yValueMin); |
| 171 | - if (index != 0) { | 173 | + |
| 172 | - CGPoint point = CGPointMake(index * _xLabelWidth + 30.0 + _xLabelWidth / 2.0, _chartCavanHeight - (innerGrade * _chartCavanHeight) + _xLabelHeight); | 174 | + CGPoint point = CGPointMake(2*_chartMargin + (i * _xLabelWidth), _chartCavanHeight - (innerGrade * _chartCavanHeight) + ( _yLabelHeight /2 )); |
| 173 | - [linePointsArray addObject:[NSValue valueWithCGPoint:point]]; | 175 | + |
| 176 | + if (i != 0) { | ||
| 174 | [progressline addLineToPoint:point]; | 177 | [progressline addLineToPoint:point]; |
| 175 | - [progressline moveToPoint:point]; | ||
| 176 | } | 178 | } |
| 177 | - index += 1; | 179 | + |
| 180 | + [progressline moveToPoint:point]; | ||
| 181 | + [linePointsArray addObject:[NSValue valueWithCGPoint:point]]; | ||
| 178 | } | 182 | } |
| 179 | [_pathPoints addObject:[linePointsArray copy]]; | 183 | [_pathPoints addObject:[linePointsArray copy]]; |
| 180 | // setup the color of the chart line | 184 | // setup the color of the chart line |
| @@ -183,38 +187,38 @@ | @@ -183,38 +187,38 @@ | ||
| 183 | }else{ | 187 | }else{ |
| 184 | chartLine.strokeColor = [PNGreen CGColor]; | 188 | chartLine.strokeColor = [PNGreen CGColor]; |
| 185 | } | 189 | } |
| 186 | - | 190 | + |
| 187 | [progressline stroke]; | 191 | [progressline stroke]; |
| 188 | - | 192 | + |
| 189 | chartLine.path = progressline.CGPath; | 193 | chartLine.path = progressline.CGPath; |
| 190 | - | 194 | + |
| 191 | CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; | 195 | CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; |
| 192 | pathAnimation.duration = 1.0; | 196 | pathAnimation.duration = 1.0; |
| 193 | pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; | 197 | pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; |
| 194 | pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f]; | 198 | pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f]; |
| 195 | pathAnimation.toValue = [NSNumber numberWithFloat:1.0f]; | 199 | pathAnimation.toValue = [NSNumber numberWithFloat:1.0f]; |
| 196 | [chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; | 200 | [chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; |
| 197 | - | 201 | + |
| 198 | chartLine.strokeEnd = 1.0; | 202 | chartLine.strokeEnd = 1.0; |
| 199 | - | 203 | + |
| 200 | UIGraphicsEndImageContext(); | 204 | UIGraphicsEndImageContext(); |
| 201 | } | 205 | } |
| 202 | } | 206 | } |
| 203 | 207 | ||
| 204 | - (void)setChartData:(NSArray *)data { | 208 | - (void)setChartData:(NSArray *)data { |
| 205 | if (data != _chartData) { | 209 | if (data != _chartData) { |
| 206 | - | 210 | + |
| 207 | NSMutableArray *yLabelsArray = [NSMutableArray arrayWithCapacity:data.count]; | 211 | NSMutableArray *yLabelsArray = [NSMutableArray arrayWithCapacity:data.count]; |
| 208 | CGFloat yMax = 0.0f; | 212 | CGFloat yMax = 0.0f; |
| 209 | - | 213 | + CGFloat yMin = MAXFLOAT; |
| 210 | // remove all shape layers before adding new ones | 214 | // remove all shape layers before adding new ones |
| 211 | for (CALayer *layer in self.chartLineArray) { | 215 | for (CALayer *layer in self.chartLineArray) { |
| 212 | [layer removeFromSuperlayer]; | 216 | [layer removeFromSuperlayer]; |
| 213 | } | 217 | } |
| 214 | self.chartLineArray = [NSMutableArray arrayWithCapacity:data.count]; | 218 | self.chartLineArray = [NSMutableArray arrayWithCapacity:data.count]; |
| 215 | - | 219 | + |
| 216 | for (PNLineChartData *chartData in data) { | 220 | for (PNLineChartData *chartData in data) { |
| 217 | - | 221 | + |
| 218 | // create as many chart line layers as there are data-lines | 222 | // create as many chart line layers as there are data-lines |
| 219 | CAShapeLayer *chartLine = [CAShapeLayer layer]; | 223 | CAShapeLayer *chartLine = [CAShapeLayer layer]; |
| 220 | chartLine.lineCap = kCALineCapRound; | 224 | chartLine.lineCap = kCALineCapRound; |
| @@ -224,27 +228,34 @@ | @@ -224,27 +228,34 @@ | ||
| 224 | chartLine.strokeEnd = 0.0; | 228 | chartLine.strokeEnd = 0.0; |
| 225 | [self.layer addSublayer:chartLine]; | 229 | [self.layer addSublayer:chartLine]; |
| 226 | [self.chartLineArray addObject:chartLine]; | 230 | [self.chartLineArray addObject:chartLine]; |
| 227 | - | 231 | + |
| 228 | for (NSUInteger i = 0; i < chartData.itemCount; i++) { | 232 | for (NSUInteger i = 0; i < chartData.itemCount; i++) { |
| 229 | PNLineChartDataItem *dataItem = chartData.getData(i); | 233 | PNLineChartDataItem *dataItem = chartData.getData(i); |
| 230 | CGFloat yValue = dataItem.y; | 234 | CGFloat yValue = dataItem.y; |
| 231 | [yLabelsArray addObject:[NSString stringWithFormat:@"%2f", yValue]]; | 235 | [yLabelsArray addObject:[NSString stringWithFormat:@"%2f", yValue]]; |
| 232 | yMax = fmaxf(yMax, dataItem.y); | 236 | yMax = fmaxf(yMax, dataItem.y); |
| 237 | + yMin = fminf(yMin, dataItem.y); | ||
| 233 | } | 238 | } |
| 234 | } | 239 | } |
| 235 | - | 240 | + |
| 236 | // Min value for Y label | 241 | // Min value for Y label |
| 237 | if (yMax < 5) { | 242 | if (yMax < 5) { |
| 238 | yMax = 5.0f; | 243 | yMax = 5.0f; |
| 239 | } | 244 | } |
| 245 | + if (yMin < 0){ | ||
| 246 | + yMin = 0.0f; | ||
| 247 | + } | ||
| 248 | + NSLog(@"%f",yMin); | ||
| 249 | + | ||
| 250 | + _yValueMin = yMin; | ||
| 240 | _yValueMax = yMax; | 251 | _yValueMax = yMax; |
| 241 | - | 252 | + |
| 242 | _chartData = data; | 253 | _chartData = data; |
| 243 | - | 254 | + |
| 244 | if (_showLabel) { | 255 | if (_showLabel) { |
| 245 | [self setYLabels:yLabelsArray]; | 256 | [self setYLabels:yLabelsArray]; |
| 246 | } | 257 | } |
| 247 | - | 258 | + |
| 248 | [self setNeedsDisplay]; | 259 | [self setNeedsDisplay]; |
| 249 | } | 260 | } |
| 250 | } | 261 | } |
| @@ -259,8 +270,17 @@ | @@ -259,8 +270,17 @@ | ||
| 259 | _showLabel = YES; | 270 | _showLabel = YES; |
| 260 | _pathPoints = [[NSMutableArray alloc] init]; | 271 | _pathPoints = [[NSMutableArray alloc] init]; |
| 261 | self.userInteractionEnabled = YES; | 272 | self.userInteractionEnabled = YES; |
| 262 | - _xLabelHeight = 20.0; | 273 | + |
| 263 | - _chartCavanHeight = self.frame.size.height - chartMargin * 2 - _xLabelHeight*2 ; | 274 | + _yLabelNum = 5.0; |
| 275 | + _yLabelHeight = [[[[PNChartLabel alloc] init] font] pointSize]; | ||
| 276 | + | ||
| 277 | + _chartMargin = 30; | ||
| 278 | + | ||
| 279 | + _xLabelHeight = _chartMargin; | ||
| 280 | + | ||
| 281 | + | ||
| 282 | + _chartCavanWidth = self.frame.size.width - _chartMargin *2; | ||
| 283 | + _chartCavanHeight = self.frame.size.height - _chartMargin * 2; | ||
| 264 | } | 284 | } |
| 265 | 285 | ||
| 266 | @end | 286 | @end |
-
Please register or login to post a comment