1. PNBar now allows you to specify a color for the label.
2. You can specify the border color for a PNBarChart 3. Fixed some problems in PNBarChart whereby the top and bottom margins were not being respected. 4. PNLineChart now has the same margin properties as PNBarChart so that you can overlay them and have the bars and the points in the LineChart line-up nicely. 5. You can now specify for a PNLineChart that points display their value using a font, format and color, just above the point itself. 6. A PNLineChartDataItem can now have two values, a raw value for displaying via the formatter, and the graded value which is used to determine the position of the data point. The former is new. This allows you to have multiple line charts that have different min-max values and yet overlay them. The new value can then be used to display a value meaningful to the user whilst the old value is used to render the chart point.
Showing
10 changed files
with
110 additions
and
67 deletions
PNChart/PNBar.h
100644 → 100755
| @@ -26,6 +26,9 @@ | @@ -26,6 +26,9 @@ | ||
| 26 | @property (nonatomic) CAShapeLayer *gradeLayer; | 26 | @property (nonatomic) CAShapeLayer *gradeLayer; |
| 27 | @property (nonatomic) CATextLayer* textLayer; | 27 | @property (nonatomic) CATextLayer* textLayer; |
| 28 | 28 | ||
| 29 | +/** Text color for all bars in the chart. */ | ||
| 30 | +@property (nonatomic) UIColor * labelTextColor; | ||
| 31 | + | ||
| 29 | @property (nonatomic, assign) BOOL isNegative; //!< 是否是负数 | 32 | @property (nonatomic, assign) BOOL isNegative; //!< 是否是负数 |
| 30 | @property (nonatomic, assign) BOOL isShowNumber; //!< 是否显示numbers | 33 | @property (nonatomic, assign) BOOL isShowNumber; //!< 是否显示numbers |
| 31 | @end | 34 | @end |
PNChart/PNBar.m
100644 → 100755
| @@ -181,7 +181,7 @@ | @@ -181,7 +181,7 @@ | ||
| 181 | _textLayer = [[CATextLayer alloc]init]; | 181 | _textLayer = [[CATextLayer alloc]init]; |
| 182 | [_textLayer setString:@"0"]; | 182 | [_textLayer setString:@"0"]; |
| 183 | [_textLayer setAlignmentMode:kCAAlignmentCenter]; | 183 | [_textLayer setAlignmentMode:kCAAlignmentCenter]; |
| 184 | - [_textLayer setForegroundColor:[[UIColor colorWithRed:178/255.0 green:178/255. blue:178/255.0 alpha:1.0] CGColor]]; | 184 | + [_textLayer setForegroundColor:[_labelTextColor CGColor]]; |
| 185 | _textLayer.hidden = YES; | 185 | _textLayer.hidden = YES; |
| 186 | 186 | ||
| 187 | } | 187 | } |
| @@ -189,6 +189,11 @@ | @@ -189,6 +189,11 @@ | ||
| 189 | return _textLayer; | 189 | return _textLayer; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | +- (void) setLabelTextColor:(UIColor *)labelTextColor { | ||
| 193 | + _labelTextColor = labelTextColor; | ||
| 194 | + [_textLayer setForegroundColor:[_labelTextColor CGColor]]; | ||
| 195 | +} | ||
| 196 | + | ||
| 192 | -(void)setGradeFrame:(CGFloat)grade startPosY:(CGFloat)startPosY | 197 | -(void)setGradeFrame:(CGFloat)grade startPosY:(CGFloat)startPosY |
| 193 | { | 198 | { |
| 194 | CGFloat textheigt = self.bounds.size.height*self.grade; | 199 | CGFloat textheigt = self.bounds.size.height*self.grade; |
PNChart/PNBarChart.h
100644 → 100755
| @@ -63,6 +63,8 @@ typedef NSString *(^PNYLabelFormatter)(CGFloat yLabelValue); | @@ -63,6 +63,8 @@ typedef NSString *(^PNYLabelFormatter)(CGFloat yLabelValue); | ||
| 63 | /** Controls whether the chart border line should be displayed. */ | 63 | /** Controls whether the chart border line should be displayed. */ |
| 64 | @property (nonatomic) BOOL showChartBorder; | 64 | @property (nonatomic) BOOL showChartBorder; |
| 65 | 65 | ||
| 66 | +@property (nonatomic) UIColor *chartBorderColor; | ||
| 67 | + | ||
| 66 | /** Controls whether the chart Horizontal separator should be displayed. */ | 68 | /** Controls whether the chart Horizontal separator should be displayed. */ |
| 67 | @property (nonatomic, assign) BOOL showLevelLine; | 69 | @property (nonatomic, assign) BOOL showLevelLine; |
| 68 | 70 |
PNChart/PNBarChart.m
100644 → 100755
| @@ -62,6 +62,7 @@ | @@ -62,6 +62,7 @@ | ||
| 62 | _chartMarginBottom = 25.0; | 62 | _chartMarginBottom = 25.0; |
| 63 | _barRadius = 2.0; | 63 | _barRadius = 2.0; |
| 64 | _showChartBorder = NO; | 64 | _showChartBorder = NO; |
| 65 | + _chartBorderColor = PNLightGrey; | ||
| 65 | _showLevelLine = NO; | 66 | _showLevelLine = NO; |
| 66 | _yChartLabelWidth = 18; | 67 | _yChartLabelWidth = 18; |
| 67 | _rotateForXAxisText = false; | 68 | _rotateForXAxisText = false; |
| @@ -234,7 +235,7 @@ | @@ -234,7 +235,7 @@ | ||
| 234 | } | 235 | } |
| 235 | 236 | ||
| 236 | bar = [[PNBar alloc] initWithFrame:CGRectMake(barXPosition, //Bar X position | 237 | bar = [[PNBar alloc] initWithFrame:CGRectMake(barXPosition, //Bar X position |
| 237 | - self.frame.size.height - chartCavanHeight - kXLabelHeight - _chartMarginTop , //Bar Y position | 238 | + self.frame.size.height - chartCavanHeight - kXLabelHeight - _chartMarginBottom + _chartMarginTop , //Bar Y position |
| 238 | barWidth, // Bar witdh | 239 | barWidth, // Bar witdh |
| 239 | self.showLevelLine ? chartCavanHeight/2.0:chartCavanHeight)]; //Bar height | 240 | self.showLevelLine ? chartCavanHeight/2.0:chartCavanHeight)]; //Bar height |
| 240 | 241 | ||
| @@ -249,6 +250,10 @@ | @@ -249,6 +250,10 @@ | ||
| 249 | }else{ | 250 | }else{ |
| 250 | bar.barColor = [self barColorAtIndex:index]; | 251 | bar.barColor = [self barColorAtIndex:index]; |
| 251 | } | 252 | } |
| 253 | + | ||
| 254 | + if (self.labelTextColor) { | ||
| 255 | + bar.labelTextColor = self.labelTextColor; | ||
| 256 | + } | ||
| 252 | 257 | ||
| 253 | // Add gradient | 258 | // Add gradient |
| 254 | if (self.isGradientShow) { | 259 | if (self.isGradientShow) { |
| @@ -309,13 +314,13 @@ | @@ -309,13 +314,13 @@ | ||
| 309 | 314 | ||
| 310 | UIBezierPath *progressline = [UIBezierPath bezierPath]; | 315 | UIBezierPath *progressline = [UIBezierPath bezierPath]; |
| 311 | 316 | ||
| 312 | - [progressline moveToPoint:CGPointMake(_chartMarginLeft, self.frame.size.height - kXLabelHeight - _chartMarginTop)]; | 317 | + [progressline moveToPoint:CGPointMake(_chartMarginLeft, self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)]; |
| 313 | - [progressline addLineToPoint:CGPointMake(self.frame.size.width - _chartMarginRight, self.frame.size.height - kXLabelHeight - _chartMarginTop)]; | 318 | + [progressline addLineToPoint:CGPointMake(self.frame.size.width - _chartMarginRight, self.frame.size.height - kXLabelHeight - _chartMarginBottom + _chartMarginTop)]; |
| 314 | 319 | ||
| 315 | [progressline setLineWidth:1.0]; | 320 | [progressline setLineWidth:1.0]; |
| 316 | [progressline setLineCapStyle:kCGLineCapSquare]; | 321 | [progressline setLineCapStyle:kCGLineCapSquare]; |
| 317 | _chartBottomLine.path = progressline.CGPath; | 322 | _chartBottomLine.path = progressline.CGPath; |
| 318 | - _chartBottomLine.strokeColor = PNLightGrey.CGColor; | 323 | + _chartBottomLine.strokeColor = [_chartBorderColor CGColor];; |
| 319 | 324 | ||
| 320 | CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; | 325 | CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; |
| 321 | pathAnimation.duration = 0.5; | 326 | pathAnimation.duration = 0.5; |
| @@ -344,7 +349,7 @@ | @@ -344,7 +349,7 @@ | ||
| 344 | [progressLeftline setLineWidth:1.0]; | 349 | [progressLeftline setLineWidth:1.0]; |
| 345 | [progressLeftline setLineCapStyle:kCGLineCapSquare]; | 350 | [progressLeftline setLineCapStyle:kCGLineCapSquare]; |
| 346 | _chartLeftLine.path = progressLeftline.CGPath; | 351 | _chartLeftLine.path = progressLeftline.CGPath; |
| 347 | - _chartLeftLine.strokeColor = PNLightGrey.CGColor; | 352 | + _chartLeftLine.strokeColor = [_chartBorderColor CGColor]; |
| 348 | 353 | ||
| 349 | CABasicAnimation *pathLeftAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; | 354 | CABasicAnimation *pathLeftAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; |
| 350 | pathLeftAnimation.duration = 0.5; | 355 | pathLeftAnimation.duration = 0.5; |
PNChart/PNLineChart.h
100644 → 100755
| @@ -45,11 +45,14 @@ | @@ -45,11 +45,14 @@ | ||
| 45 | @property (nonatomic) UIColor *yLabelColor; | 45 | @property (nonatomic) UIColor *yLabelColor; |
| 46 | @property (nonatomic) CGFloat chartCavanHeight; | 46 | @property (nonatomic) CGFloat chartCavanHeight; |
| 47 | @property (nonatomic) CGFloat chartCavanWidth; | 47 | @property (nonatomic) CGFloat chartCavanWidth; |
| 48 | -@property (nonatomic) CGFloat chartMargin; | ||
| 49 | @property (nonatomic) BOOL showLabel; | 48 | @property (nonatomic) BOOL showLabel; |
| 50 | @property (nonatomic) BOOL showGenYLabels; | 49 | @property (nonatomic) BOOL showGenYLabels; |
| 51 | @property (nonatomic) BOOL thousandsSeparator; | 50 | @property (nonatomic) BOOL thousandsSeparator; |
| 52 | 51 | ||
| 52 | +@property (nonatomic) CGFloat chartMarginLeft; | ||
| 53 | +@property (nonatomic) CGFloat chartMarginRight; | ||
| 54 | +@property (nonatomic) CGFloat chartMarginTop; | ||
| 55 | +@property (nonatomic) CGFloat chartMarginBottom; | ||
| 53 | 56 | ||
| 54 | /** | 57 | /** |
| 55 | * Controls whether to show the coordinate axis. Default is NO. | 58 | * Controls whether to show the coordinate axis. Default is NO. |
PNChart/PNLineChart.m
100644 → 100755
| @@ -70,19 +70,19 @@ | @@ -70,19 +70,19 @@ | ||
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | if (yStep == 0.0) { | 72 | if (yStep == 0.0) { |
| 73 | - PNChartLabel *minLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)_chartCavanHeight, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; | 73 | + PNChartLabel *minLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)_chartCavanHeight, (NSInteger)_chartMarginBottom, (NSInteger)_yLabelHeight)]; |
| 74 | minLabel.text = [self formatYLabel:0.0]; | 74 | minLabel.text = [self formatYLabel:0.0]; |
| 75 | [self setCustomStyleForYLabel:minLabel]; | 75 | [self setCustomStyleForYLabel:minLabel]; |
| 76 | [self addSubview:minLabel]; | 76 | [self addSubview:minLabel]; |
| 77 | [_yChartLabels addObject:minLabel]; | 77 | [_yChartLabels addObject:minLabel]; |
| 78 | 78 | ||
| 79 | - PNChartLabel *midLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight / 2), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; | 79 | + PNChartLabel *midLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight / 2), (NSInteger)_chartMarginBottom, (NSInteger)_yLabelHeight)]; |
| 80 | midLabel.text = [self formatYLabel:_yValueMax]; | 80 | midLabel.text = [self formatYLabel:_yValueMax]; |
| 81 | [self setCustomStyleForYLabel:midLabel]; | 81 | [self setCustomStyleForYLabel:midLabel]; |
| 82 | [self addSubview:midLabel]; | 82 | [self addSubview:midLabel]; |
| 83 | [_yChartLabels addObject:midLabel]; | 83 | [_yChartLabels addObject:midLabel]; |
| 84 | 84 | ||
| 85 | - PNChartLabel *maxLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, 0.0, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; | 85 | + PNChartLabel *maxLabel = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, 0.0, (NSInteger)_chartMarginBottom, (NSInteger)_yLabelHeight)]; |
| 86 | maxLabel.text = [self formatYLabel:_yValueMax * 2]; | 86 | maxLabel.text = [self formatYLabel:_yValueMax * 2]; |
| 87 | [self setCustomStyleForYLabel:maxLabel]; | 87 | [self setCustomStyleForYLabel:maxLabel]; |
| 88 | [self addSubview:maxLabel]; | 88 | [self addSubview:maxLabel]; |
| @@ -94,7 +94,7 @@ | @@ -94,7 +94,7 @@ | ||
| 94 | 94 | ||
| 95 | while (num > 0) | 95 | while (num > 0) |
| 96 | { | 96 | { |
| 97 | - PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight - index * yStepHeight), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; | 97 | + PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, (NSInteger)(_chartCavanHeight - index * yStepHeight), (NSInteger)_chartMarginBottom, (NSInteger)_yLabelHeight)]; |
| 98 | [label setTextAlignment:NSTextAlignmentRight]; | 98 | [label setTextAlignment:NSTextAlignmentRight]; |
| 99 | label.text = [self formatYLabel:_yValueMin + (yStep * index)]; | 99 | label.text = [self formatYLabel:_yValueMin + (yStep * index)]; |
| 100 | [self setCustomStyleForYLabel:label]; | 100 | [self setCustomStyleForYLabel:label]; |
| @@ -143,7 +143,7 @@ | @@ -143,7 +143,7 @@ | ||
| 143 | 143 | ||
| 144 | NSInteger y = (NSInteger)(_chartCavanHeight - index * yStepHeight); | 144 | NSInteger y = (NSInteger)(_chartCavanHeight - index * yStepHeight); |
| 145 | 145 | ||
| 146 | - PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, y, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight)]; | 146 | + PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(0.0, y, (NSInteger)_chartMarginLeft * 0.9, (NSInteger)_yLabelHeight)]; |
| 147 | [label setTextAlignment:NSTextAlignmentRight]; | 147 | [label setTextAlignment:NSTextAlignmentRight]; |
| 148 | label.text = labelText; | 148 | label.text = labelText; |
| 149 | [self setCustomStyleForYLabel:label]; | 149 | [self setCustomStyleForYLabel:label]; |
| @@ -174,7 +174,7 @@ | @@ -174,7 +174,7 @@ | ||
| 174 | if (_showLabel) { | 174 | if (_showLabel) { |
| 175 | xLabelWidth = _chartCavanWidth / [xLabels count]; | 175 | xLabelWidth = _chartCavanWidth / [xLabels count]; |
| 176 | } else { | 176 | } else { |
| 177 | - xLabelWidth = (self.frame.size.width) / [xLabels count]; | 177 | + xLabelWidth = (self.frame.size.width - _chartMarginLeft - _chartMarginRight) / [xLabels count]; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | return [self setXLabels:xLabels withWidth:xLabelWidth]; | 180 | return [self setXLabels:xLabels withWidth:xLabelWidth]; |
| @@ -198,10 +198,10 @@ | @@ -198,10 +198,10 @@ | ||
| 198 | for (int index = 0; index < xLabels.count; index++) { | 198 | for (int index = 0; index < xLabels.count; index++) { |
| 199 | labelText = xLabels[index]; | 199 | labelText = xLabels[index]; |
| 200 | 200 | ||
| 201 | - NSInteger x = 2 * _chartMargin + (index * _xLabelWidth) - (_xLabelWidth / 2); | 201 | + NSInteger x = (index * _xLabelWidth + _chartMarginLeft + _xLabelWidth /2.0 ); |
| 202 | - NSInteger y = _chartMargin + _chartCavanHeight; | 202 | + NSInteger y = _chartMarginBottom + _chartCavanHeight; |
| 203 | 203 | ||
| 204 | - PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(x, y, (NSInteger)_xLabelWidth, (NSInteger)_chartMargin)]; | 204 | + PNChartLabel *label = [[PNChartLabel alloc] initWithFrame:CGRectMake(x, y, (NSInteger)_xLabelWidth, (NSInteger)_chartMarginBottom)]; |
| 205 | [label setTextAlignment:NSTextAlignmentCenter]; | 205 | [label setTextAlignment:NSTextAlignmentCenter]; |
| 206 | label.text = labelText; | 206 | label.text = labelText; |
| 207 | [self setCustomStyleForXLabel:label]; | 207 | [self setCustomStyleForXLabel:label]; |
| @@ -392,7 +392,7 @@ | @@ -392,7 +392,7 @@ | ||
| 392 | if (!_showLabel) { | 392 | if (!_showLabel) { |
| 393 | _chartCavanHeight = self.frame.size.height - 2 * _yLabelHeight; | 393 | _chartCavanHeight = self.frame.size.height - 2 * _yLabelHeight; |
| 394 | _chartCavanWidth = self.frame.size.width; | 394 | _chartCavanWidth = self.frame.size.width; |
| 395 | - _chartMargin = chartData.inflexionPointWidth; | 395 | + //_chartMargin = chartData.inflexionPointWidth; |
| 396 | _xLabelWidth = (_chartCavanWidth / ([_xLabels count] - 1)); | 396 | _xLabelWidth = (_chartCavanWidth / ([_xLabels count] - 1)); |
| 397 | } | 397 | } |
| 398 | 398 | ||
| @@ -412,10 +412,9 @@ | @@ -412,10 +412,9 @@ | ||
| 412 | innerGrade = (yValue - _yValueMin) / (_yValueMax - _yValueMin); | 412 | innerGrade = (yValue - _yValueMin) / (_yValueMax - _yValueMin); |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | - CGFloat offSetX = (_chartCavanWidth) / (chartData.itemCount); | 415 | + int x = i * _xLabelWidth + _chartMarginLeft + _xLabelWidth /2.0; |
| 416 | 416 | ||
| 417 | - int x = 2 * _chartMargin + (i * offSetX); | 417 | + int y = _chartCavanHeight - (innerGrade * _chartCavanHeight) + (_yLabelHeight / 2) + _chartMarginTop - _chartMarginBottom; |
| 418 | - int y = _chartCavanHeight - (innerGrade * _chartCavanHeight) + (_yLabelHeight / 2); | ||
| 419 | 418 | ||
| 420 | // Circular point | 419 | // Circular point |
| 421 | if (chartData.inflexionPointStyle == PNLineChartPointStyleCircle) { | 420 | if (chartData.inflexionPointStyle == PNLineChartPointStyleCircle) { |
| @@ -427,9 +426,9 @@ | @@ -427,9 +426,9 @@ | ||
| 427 | [pointPath addArcWithCenter:circleCenter radius:inflexionWidth / 2 startAngle:0 endAngle:2 * M_PI clockwise:YES]; | 426 | [pointPath addArcWithCenter:circleCenter radius:inflexionWidth / 2 startAngle:0 endAngle:2 * M_PI clockwise:YES]; |
| 428 | 427 | ||
| 429 | //jet text display text | 428 | //jet text display text |
| 430 | -// CATextLayer* textLayer = [self createTextLayer]; | 429 | + if (chartData.showPointLabel == YES) { |
| 431 | -// [self setGradeFrame:textLayer grade:yValue pointCenter:circleCenter width:inflexionWidth]; | 430 | + [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:circleCenter width:inflexionWidth withChartData:chartData]]; |
| 432 | -// [gradePathArray addObject:textLayer]; | 431 | + } |
| 433 | 432 | ||
| 434 | if ( i != 0 ) { | 433 | if ( i != 0 ) { |
| 435 | 434 | ||
| @@ -463,9 +462,9 @@ | @@ -463,9 +462,9 @@ | ||
| 463 | [pointPath closePath]; | 462 | [pointPath closePath]; |
| 464 | 463 | ||
| 465 | // text display text | 464 | // text display text |
| 466 | -// CATextLayer* textLayer = [self createTextLayer]; | 465 | + if (chartData.showPointLabel == YES) { |
| 467 | -// [self setGradeFrame:textLayer grade:yValue pointCenter:squareCenter width:inflexionWidth]; | 466 | + [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:squareCenter width:inflexionWidth withChartData:chartData]]; |
| 468 | -// [gradePathArray addObject:textLayer]; | 467 | + } |
| 469 | 468 | ||
| 470 | if ( i != 0 ) { | 469 | if ( i != 0 ) { |
| 471 | 470 | ||
| @@ -501,9 +500,9 @@ | @@ -501,9 +500,9 @@ | ||
| 501 | [pointPath closePath]; | 500 | [pointPath closePath]; |
| 502 | 501 | ||
| 503 | // text display text | 502 | // text display text |
| 504 | -// CATextLayer* textLayer = [self createTextLayer]; | 503 | + if (chartData.showPointLabel == YES) { |
| 505 | -// [self setGradeFrame:textLayer grade:yValue pointCenter:middlePoint width:inflexionWidth]; | 504 | + [gradePathArray addObject:[self createPointLabelFor:chartData.getData(i).rawY pointCenter:middlePoint width:inflexionWidth withChartData:chartData]]; |
| 506 | -// [gradePathArray addObject:textLayer]; | 505 | + } |
| 507 | 506 | ||
| 508 | if ( i != 0 ) { | 507 | if ( i != 0 ) { |
| 509 | // calculate the point for triangle | 508 | // calculate the point for triangle |
| @@ -684,19 +683,19 @@ | @@ -684,19 +683,19 @@ | ||
| 684 | CGContextSetLineWidth(ctx, self.axisWidth); | 683 | CGContextSetLineWidth(ctx, self.axisWidth); |
| 685 | CGContextSetStrokeColorWithColor(ctx, [self.axisColor CGColor]); | 684 | CGContextSetStrokeColorWithColor(ctx, [self.axisColor CGColor]); |
| 686 | 685 | ||
| 687 | - CGFloat xAxisWidth = CGRectGetWidth(rect) - _chartMargin / 2; | 686 | + CGFloat xAxisWidth = CGRectGetWidth(rect) - (_chartMarginLeft + _chartMarginRight) / 2; |
| 688 | - CGFloat yAxisHeight = _chartMargin + _chartCavanHeight; | 687 | + CGFloat yAxisHeight = _chartMarginBottom + _chartCavanHeight; |
| 689 | 688 | ||
| 690 | // draw coordinate axis | 689 | // draw coordinate axis |
| 691 | - CGContextMoveToPoint(ctx, _chartMargin + yAxisOffset, 0); | 690 | + CGContextMoveToPoint(ctx, _chartMarginBottom + yAxisOffset, 0); |
| 692 | - CGContextAddLineToPoint(ctx, _chartMargin + yAxisOffset, yAxisHeight); | 691 | + CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset, yAxisHeight); |
| 693 | CGContextAddLineToPoint(ctx, xAxisWidth, yAxisHeight); | 692 | CGContextAddLineToPoint(ctx, xAxisWidth, yAxisHeight); |
| 694 | CGContextStrokePath(ctx); | 693 | CGContextStrokePath(ctx); |
| 695 | 694 | ||
| 696 | // draw y axis arrow | 695 | // draw y axis arrow |
| 697 | - CGContextMoveToPoint(ctx, _chartMargin + yAxisOffset - 3, 6); | 696 | + CGContextMoveToPoint(ctx, _chartMarginBottom + yAxisOffset - 3, 6); |
| 698 | - CGContextAddLineToPoint(ctx, _chartMargin + yAxisOffset, 0); | 697 | + CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset, 0); |
| 699 | - CGContextAddLineToPoint(ctx, _chartMargin + yAxisOffset + 3, 6); | 698 | + CGContextAddLineToPoint(ctx, _chartMarginBottom + yAxisOffset + 3, 6); |
| 700 | CGContextStrokePath(ctx); | 699 | CGContextStrokePath(ctx); |
| 701 | 700 | ||
| 702 | // draw x axis arrow | 701 | // draw x axis arrow |
| @@ -710,7 +709,7 @@ | @@ -710,7 +709,7 @@ | ||
| 710 | // draw x axis separator | 709 | // draw x axis separator |
| 711 | CGPoint point; | 710 | CGPoint point; |
| 712 | for (NSUInteger i = 0; i < [self.xLabels count]; i++) { | 711 | for (NSUInteger i = 0; i < [self.xLabels count]; i++) { |
| 713 | - point = CGPointMake(2 * _chartMargin + (i * _xLabelWidth), _chartMargin + _chartCavanHeight); | 712 | + point = CGPointMake(2 * _chartMarginLeft + (i * _xLabelWidth), _chartMarginBottom + _chartCavanHeight); |
| 714 | CGContextMoveToPoint(ctx, point.x, point.y - 2); | 713 | CGContextMoveToPoint(ctx, point.x, point.y - 2); |
| 715 | CGContextAddLineToPoint(ctx, point.x, point.y); | 714 | CGContextAddLineToPoint(ctx, point.x, point.y); |
| 716 | CGContextStrokePath(ctx); | 715 | CGContextStrokePath(ctx); |
| @@ -719,7 +718,7 @@ | @@ -719,7 +718,7 @@ | ||
| 719 | // draw y axis separator | 718 | // draw y axis separator |
| 720 | CGFloat yStepHeight = _chartCavanHeight / _yLabelNum; | 719 | CGFloat yStepHeight = _chartCavanHeight / _yLabelNum; |
| 721 | for (NSUInteger i = 0; i < [self.xLabels count]; i++) { | 720 | for (NSUInteger i = 0; i < [self.xLabels count]; i++) { |
| 722 | - point = CGPointMake(_chartMargin + yAxisOffset, (_chartCavanHeight - i * yStepHeight + _yLabelHeight / 2)); | 721 | + point = CGPointMake(_chartMarginBottom + yAxisOffset, (_chartCavanHeight - i * yStepHeight + _yLabelHeight / 2)); |
| 723 | CGContextMoveToPoint(ctx, point.x, point.y); | 722 | CGContextMoveToPoint(ctx, point.x, point.y); |
| 724 | CGContextAddLineToPoint(ctx, point.x + 2, point.y); | 723 | CGContextAddLineToPoint(ctx, point.x + 2, point.y); |
| 725 | CGContextStrokePath(ctx); | 724 | CGContextStrokePath(ctx); |
| @@ -731,14 +730,14 @@ | @@ -731,14 +730,14 @@ | ||
| 731 | // draw y unit | 730 | // draw y unit |
| 732 | if ([self.yUnit length]) { | 731 | if ([self.yUnit length]) { |
| 733 | CGFloat height = [PNLineChart sizeOfString:self.yUnit withWidth:30.f font:font].height; | 732 | CGFloat height = [PNLineChart sizeOfString:self.yUnit withWidth:30.f font:font].height; |
| 734 | - CGRect drawRect = CGRectMake(_chartMargin + 10 + 5, 0, 30.f, height); | 733 | + CGRect drawRect = CGRectMake(_chartMarginLeft + 10 + 5, 0, 30.f, height); |
| 735 | [self drawTextInContext:ctx text:self.yUnit inRect:drawRect font:font]; | 734 | [self drawTextInContext:ctx text:self.yUnit inRect:drawRect font:font]; |
| 736 | } | 735 | } |
| 737 | 736 | ||
| 738 | // draw x unit | 737 | // draw x unit |
| 739 | if ([self.xUnit length]) { | 738 | if ([self.xUnit length]) { |
| 740 | CGFloat height = [PNLineChart sizeOfString:self.xUnit withWidth:30.f font:font].height; | 739 | CGFloat height = [PNLineChart sizeOfString:self.xUnit withWidth:30.f font:font].height; |
| 741 | - CGRect drawRect = CGRectMake(CGRectGetWidth(rect) - _chartMargin + 5, _chartMargin + _chartCavanHeight - height / 2, 25.f, height); | 740 | + CGRect drawRect = CGRectMake(CGRectGetWidth(rect) - _chartMarginLeft + 5, _chartMarginBottom + _chartCavanHeight - height / 2, 25.f, height); |
| 742 | [self drawTextInContext:ctx text:self.xUnit inRect:drawRect font:font]; | 741 | [self drawTextInContext:ctx text:self.xUnit inRect:drawRect font:font]; |
| 743 | } | 742 | } |
| 744 | } | 743 | } |
| @@ -766,15 +765,23 @@ | @@ -766,15 +765,23 @@ | ||
| 766 | _yLabelNum = 5.0; | 765 | _yLabelNum = 5.0; |
| 767 | _yLabelHeight = [[[[PNChartLabel alloc] init] font] pointSize]; | 766 | _yLabelHeight = [[[[PNChartLabel alloc] init] font] pointSize]; |
| 768 | 767 | ||
| 769 | - _chartMargin = 40; | 768 | +// _chartMargin = 40; |
| 769 | + | ||
| 770 | + _chartMarginLeft = 25.0; | ||
| 771 | + _chartMarginRight = 25.0; | ||
| 772 | + _chartMarginTop = 25.0; | ||
| 773 | + _chartMarginBottom = 25.0; | ||
| 774 | + | ||
| 775 | + _yLabelFormat = @"%1.f"; | ||
| 770 | 776 | ||
| 771 | - _chartCavanWidth = self.frame.size.width - _chartMargin * 2; | 777 | + _chartCavanWidth = self.frame.size.width - _chartMarginLeft - _chartMarginRight; |
| 772 | - _chartCavanHeight = self.frame.size.height - _chartMargin * 2; | 778 | + _chartCavanHeight = self.frame.size.height - _chartMarginBottom - _chartMarginTop; |
| 773 | 779 | ||
| 774 | // Coordinate Axis Default Values | 780 | // Coordinate Axis Default Values |
| 775 | _showCoordinateAxis = NO; | 781 | _showCoordinateAxis = NO; |
| 776 | _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f]; | 782 | _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f]; |
| 777 | _axisWidth = 1.f; | 783 | _axisWidth = 1.f; |
| 784 | + | ||
| 778 | } | 785 | } |
| 779 | 786 | ||
| 780 | #pragma mark - tools | 787 | #pragma mark - tools |
| @@ -1001,36 +1008,38 @@ | @@ -1001,36 +1008,38 @@ | ||
| 1001 | 1008 | ||
| 1002 | #pragma mark setter and getter | 1009 | #pragma mark setter and getter |
| 1003 | 1010 | ||
| 1004 | --(CATextLayer*)createTextLayer | 1011 | +-(CATextLayer*) createPointLabelFor:(CGFloat)grade pointCenter:(CGPoint)pointCenter width:(CGFloat)width withChartData:(PNLineChartData*)chartData |
| 1005 | { | 1012 | { |
| 1006 | - CATextLayer * textLayer = [[CATextLayer alloc]init]; | 1013 | + CATextLayer *textLayer = [[CATextLayer alloc]init]; |
| 1007 | - [textLayer setString:@"0"]; | ||
| 1008 | [textLayer setAlignmentMode:kCAAlignmentCenter]; | 1014 | [textLayer setAlignmentMode:kCAAlignmentCenter]; |
| 1009 | - [textLayer setForegroundColor:[[UIColor blackColor] CGColor]]; | 1015 | + [textLayer setForegroundColor:[chartData.pointLabelColor CGColor]]; |
| 1010 | - return textLayer; | 1016 | + [textLayer setBackgroundColor:[[[UIColor whiteColor] colorWithAlphaComponent:0.8] CGColor]]; |
| 1011 | -} | 1017 | + [textLayer setCornerRadius:textLayer.fontSize/8.0]; |
| 1012 | - | ||
| 1013 | --(void)setGradeFrame:(CATextLayer*)textLayer grade:(CGFloat)grade pointCenter:(CGPoint)pointCenter width:(CGFloat)width | ||
| 1014 | -{ | ||
| 1015 | - CGFloat textheigt = width*3; | ||
| 1016 | - CGFloat textWidth = width*8; | ||
| 1017 | - CGFloat textStartPosY; | ||
| 1018 | 1018 | ||
| 1019 | - if (pointCenter.y > textheigt) { | 1019 | + if (chartData.pointLabelFont != nil) { |
| 1020 | - textStartPosY = pointCenter.y - textheigt; | 1020 | + [textLayer setFont:(__bridge CFTypeRef)(chartData.pointLabelFont)]; |
| 1021 | - } | 1021 | + textLayer.fontSize = [chartData.pointLabelFont pointSize]; |
| 1022 | - else { | ||
| 1023 | - textStartPosY = pointCenter.y; | ||
| 1024 | } | 1022 | } |
| 1025 | 1023 | ||
| 1024 | + CGFloat textHeight = textLayer.fontSize * 1.1; | ||
| 1025 | + CGFloat textWidth = width*8; | ||
| 1026 | + CGFloat textStartPosY; | ||
| 1027 | + | ||
| 1028 | + textStartPosY = pointCenter.y - textLayer.fontSize; | ||
| 1029 | + | ||
| 1026 | [self.layer addSublayer:textLayer]; | 1030 | [self.layer addSublayer:textLayer]; |
| 1027 | - [textLayer setFontSize:textheigt/2]; | ||
| 1028 | 1031 | ||
| 1029 | - [textLayer setString:[[NSString alloc]initWithFormat:@"%d",(int)(grade*100)]]; | 1032 | + if (chartData.pointLabelFormat != nil) { |
| 1030 | - [textLayer setFrame:CGRectMake(0, 0, textWidth, textheigt)]; | 1033 | + [textLayer setString:[[NSString alloc]initWithFormat:chartData.pointLabelFormat, grade]]; |
| 1034 | + } else { | ||
| 1035 | + [textLayer setString:[[NSString alloc]initWithFormat:_yLabelFormat, grade]]; | ||
| 1036 | + } | ||
| 1037 | + | ||
| 1038 | + [textLayer setFrame:CGRectMake(0, 0, textWidth, textHeight)]; | ||
| 1031 | [textLayer setPosition:CGPointMake(pointCenter.x, textStartPosY)]; | 1039 | [textLayer setPosition:CGPointMake(pointCenter.x, textStartPosY)]; |
| 1032 | textLayer.contentsScale = [UIScreen mainScreen].scale; | 1040 | textLayer.contentsScale = [UIScreen mainScreen].scale; |
| 1033 | 1041 | ||
| 1042 | + return textLayer; | ||
| 1034 | } | 1043 | } |
| 1035 | 1044 | ||
| 1036 | -(CABasicAnimation*)fadeAnimation | 1045 | -(CABasicAnimation*)fadeAnimation |
PNChart/PNLineChartData.h
100644 → 100755
| @@ -25,6 +25,11 @@ typedef PNLineChartDataItem *(^LCLineChartDataGetter)(NSUInteger item); | @@ -25,6 +25,11 @@ typedef PNLineChartDataItem *(^LCLineChartDataGetter)(NSUInteger item); | ||
| 25 | @property (copy) LCLineChartDataGetter getData; | 25 | @property (copy) LCLineChartDataGetter getData; |
| 26 | @property (strong, nonatomic) NSString *dataTitle; | 26 | @property (strong, nonatomic) NSString *dataTitle; |
| 27 | 27 | ||
| 28 | +@property (nonatomic) BOOL showPointLabel; | ||
| 29 | +@property (nonatomic) UIColor *pointLabelColor; | ||
| 30 | +@property (nonatomic) UIFont *pointLabelFont; | ||
| 31 | +@property (nonatomic) NSString *pointLabelFormat; | ||
| 32 | + | ||
| 28 | @property (nonatomic, assign) PNLineChartPointStyle inflexionPointStyle; | 33 | @property (nonatomic, assign) PNLineChartPointStyle inflexionPointStyle; |
| 29 | 34 | ||
| 30 | /** | 35 | /** |
PNChart/PNLineChartData.m
100644 → 100755
| @@ -23,6 +23,9 @@ | @@ -23,6 +23,9 @@ | ||
| 23 | _inflexionPointWidth = 6.f; | 23 | _inflexionPointWidth = 6.f; |
| 24 | _lineWidth = 2.f; | 24 | _lineWidth = 2.f; |
| 25 | _alpha = 1.f; | 25 | _alpha = 1.f; |
| 26 | + _showPointLabel = NO; | ||
| 27 | + _pointLabelColor = [UIColor blackColor]; | ||
| 28 | + _pointLabelFormat = @"%1.f"; | ||
| 26 | } | 29 | } |
| 27 | 30 | ||
| 28 | @end | 31 | @end |
PNChart/PNLineChartDataItem.h
100644 → 100755
| @@ -9,7 +9,9 @@ | @@ -9,7 +9,9 @@ | ||
| 9 | @interface PNLineChartDataItem : NSObject | 9 | @interface PNLineChartDataItem : NSObject |
| 10 | 10 | ||
| 11 | + (PNLineChartDataItem *)dataItemWithY:(CGFloat)y; | 11 | + (PNLineChartDataItem *)dataItemWithY:(CGFloat)y; |
| 12 | ++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y andRawY:(CGFloat)rawY; | ||
| 12 | 13 | ||
| 13 | @property (readonly) CGFloat y; // should be within the y range | 14 | @property (readonly) CGFloat y; // should be within the y range |
| 15 | +@property (readonly) CGFloat rawY; // this is the raw value, used for point label. | ||
| 14 | 16 | ||
| 15 | @end | 17 | @end |
PNChart/PNLineChartDataItem.m
100644 → 100755
| @@ -7,9 +7,10 @@ | @@ -7,9 +7,10 @@ | ||
| 7 | 7 | ||
| 8 | @interface PNLineChartDataItem () | 8 | @interface PNLineChartDataItem () |
| 9 | 9 | ||
| 10 | -- (id)initWithY:(CGFloat)y; | 10 | +- (id)initWithY:(CGFloat)y andRawY:(CGFloat)rawY; |
| 11 | 11 | ||
| 12 | -@property (readwrite) CGFloat y; // should be within the y range | 12 | +@property (readwrite) CGFloat y; // should be within the y range |
| 13 | +@property (readwrite) CGFloat rawY; // this is the raw value, used for point label. | ||
| 13 | 14 | ||
| 14 | @end | 15 | @end |
| 15 | 16 | ||
| @@ -17,13 +18,18 @@ | @@ -17,13 +18,18 @@ | ||
| 17 | 18 | ||
| 18 | + (PNLineChartDataItem *)dataItemWithY:(CGFloat)y | 19 | + (PNLineChartDataItem *)dataItemWithY:(CGFloat)y |
| 19 | { | 20 | { |
| 20 | - return [[PNLineChartDataItem alloc] initWithY:y]; | 21 | + return [[PNLineChartDataItem alloc] initWithY:y andRawY:y]; |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | -- (id)initWithY:(CGFloat)y | 24 | ++ (PNLineChartDataItem *)dataItemWithY:(CGFloat)y andRawY:(CGFloat)rawY { |
| 25 | + return [[PNLineChartDataItem alloc] initWithY:y andRawY:rawY]; | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +- (id)initWithY:(CGFloat)y andRawY:(CGFloat)rawY | ||
| 24 | { | 29 | { |
| 25 | if ((self = [super init])) { | 30 | if ((self = [super init])) { |
| 26 | self.y = y; | 31 | self.y = y; |
| 32 | + self.rawY = rawY; | ||
| 27 | } | 33 | } |
| 28 | 34 | ||
| 29 | return self; | 35 | return self; |
-
Please register or login to post a comment