kevinzhow

New calculateChartPath method

@@ -59,4 +59,10 @@ @@ -59,4 +59,10 @@
59 59
60 - (void)setXLabels:(NSArray *)xLabels withWidth:(CGFloat)width; 60 - (void)setXLabels:(NSArray *)xLabels withWidth:(CGFloat)width;
61 61
  62 +/**
  63 + * Update Chart Value
  64 + */
  65 +
  66 +- (void)updateChartData:(NSArray *)data;
  67 +
62 @end 68 @end
@@ -150,6 +150,8 @@ @@ -150,6 +150,8 @@
150 } 150 }
151 } 151 }
152 152
  153 +#pragma mark - Touch at point
  154 +
153 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 155 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
154 { 156 {
155 [self touchPoint:touches withEvent:event]; 157 [self touchPoint:touches withEvent:event];
@@ -224,111 +226,157 @@ @@ -224,111 +226,157 @@
224 } 226 }
225 } 227 }
226 228
  229 +#pragma mark - Draw Chart
  230 +
227 - (void)strokeChart 231 - (void)strokeChart
228 { 232 {
229 _chartPath = [[NSMutableArray alloc] init]; 233 _chartPath = [[NSMutableArray alloc] init];
230 _pointPath = [[NSMutableArray alloc] init]; 234 _pointPath = [[NSMutableArray alloc] init];
231 235
  236 + [self calculateChartPath:_chartPath andPointsPath:_pointPath andPathKeyPoints:_pathPoints];
232 // Draw each line 237 // Draw each line
233 for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) { 238 for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
234 PNLineChartData *chartData = self.chartData[lineIndex]; 239 PNLineChartData *chartData = self.chartData[lineIndex];
235 CAShapeLayer *chartLine = (CAShapeLayer *)self.chartLineArray[lineIndex]; 240 CAShapeLayer *chartLine = (CAShapeLayer *)self.chartLineArray[lineIndex];
236 CAShapeLayer *pointLayer = (CAShapeLayer *)self.chartPointArray[lineIndex]; 241 CAShapeLayer *pointLayer = (CAShapeLayer *)self.chartPointArray[lineIndex];
  242 + UIGraphicsBeginImageContext(self.frame.size);
  243 + // setup the color of the chart line
  244 + if (chartData.color) {
  245 + chartLine.strokeColor = [chartData.color CGColor];
  246 + } else {
  247 + chartLine.strokeColor = [PNGreen CGColor];
  248 + pointLayer.strokeColor = [PNGreen CGColor];
  249 + }
  250 +
  251 + UIBezierPath *progressline = [_chartPath objectAtIndex:lineIndex];
  252 + UIBezierPath *pointPath = [_pointPath objectAtIndex:lineIndex];
  253 +
  254 + chartLine.path = progressline.CGPath;
  255 + pointLayer.path = pointPath.CGPath;
  256 +
  257 + [CATransaction begin];
  258 + CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  259 + pathAnimation.duration = 1.0;
  260 + pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  261 + pathAnimation.fromValue = @0.0f;
  262 + pathAnimation.toValue = @1.0f;
  263 +
  264 + [chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
  265 + chartLine.strokeEnd = 1.0;
  266 +
  267 + // if you want cancel the point animation, conment this code, the point will show immediately
  268 + if (chartData.inflexionPointStyle != PNLineChartPointStyleNone) {
  269 + [pointLayer addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
  270 + }
  271 +
  272 + [CATransaction commit];
237 273
  274 + UIGraphicsEndImageContext();
  275 + }
  276 +}
  277 +
  278 +
  279 +- (void)calculateChartPath:(NSMutableArray *)chartPath andPointsPath:(NSMutableArray *)pointsPath andPathKeyPoints:(NSMutableArray *)pathPoints
  280 +{
  281 +
  282 + // Draw each line
  283 + for (NSUInteger lineIndex = 0; lineIndex < self.chartData.count; lineIndex++) {
  284 + PNLineChartData *chartData = self.chartData[lineIndex];
  285 +
238 CGFloat yValue; 286 CGFloat yValue;
239 CGFloat innerGrade; 287 CGFloat innerGrade;
240 288
241 - UIGraphicsBeginImageContext(self.frame.size); 289 +
242 -  
243 UIBezierPath *progressline = [UIBezierPath bezierPath]; 290 UIBezierPath *progressline = [UIBezierPath bezierPath];
244 [progressline setLineWidth:chartData.lineWidth]; 291 [progressline setLineWidth:chartData.lineWidth];
245 [progressline setLineCapStyle:kCGLineCapRound]; 292 [progressline setLineCapStyle:kCGLineCapRound];
246 [progressline setLineJoinStyle:kCGLineJoinRound]; 293 [progressline setLineJoinStyle:kCGLineJoinRound];
247 - 294 +
248 UIBezierPath *pointPath = [UIBezierPath bezierPath]; 295 UIBezierPath *pointPath = [UIBezierPath bezierPath];
249 [pointPath setLineWidth:chartData.lineWidth]; 296 [pointPath setLineWidth:chartData.lineWidth];
250 - 297 +
251 - [_chartPath addObject:progressline]; 298 +
252 - [_pointPath addObject:pointPath]; 299 + [chartPath insertObject:progressline atIndex:lineIndex];
253 - 300 + [pointsPath insertObject:pointPath atIndex:lineIndex];
  301 +
254 if (!_showLabel) { 302 if (!_showLabel) {
255 _chartCavanHeight = self.frame.size.height - 2 * _yLabelHeight; 303 _chartCavanHeight = self.frame.size.height - 2 * _yLabelHeight;
256 _chartCavanWidth = self.frame.size.width; 304 _chartCavanWidth = self.frame.size.width;
257 _chartMargin = chartData.inflexionPointWidth; 305 _chartMargin = chartData.inflexionPointWidth;
258 _xLabelWidth = (_chartCavanWidth / ([_xLabels count] - 1)); 306 _xLabelWidth = (_chartCavanWidth / ([_xLabels count] - 1));
259 } 307 }
260 - 308 +
261 NSMutableArray *linePointsArray = [[NSMutableArray alloc] init]; 309 NSMutableArray *linePointsArray = [[NSMutableArray alloc] init];
262 - 310 +
263 int last_x = 0; 311 int last_x = 0;
264 int last_y = 0; 312 int last_y = 0;
265 CGFloat inflexionWidth = chartData.inflexionPointWidth; 313 CGFloat inflexionWidth = chartData.inflexionPointWidth;
266 - 314 +
267 for (NSUInteger i = 0; i < chartData.itemCount; i++) { 315 for (NSUInteger i = 0; i < chartData.itemCount; i++) {
268 - 316 +
269 yValue = chartData.getData(i).y; 317 yValue = chartData.getData(i).y;
270 - 318 +
271 if (!(_yValueMax - _yValueMin)) { 319 if (!(_yValueMax - _yValueMin)) {
272 innerGrade = 0.5; 320 innerGrade = 0.5;
273 } else { 321 } else {
274 innerGrade = (yValue - _yValueMin) / (_yValueMax - _yValueMin); 322 innerGrade = (yValue - _yValueMin) / (_yValueMax - _yValueMin);
275 } 323 }
276 - 324 +
277 CGFloat offSetX = (_chartCavanWidth) / (chartData.itemCount); 325 CGFloat offSetX = (_chartCavanWidth) / (chartData.itemCount);
278 - 326 +
279 int x = 2 * _chartMargin + (i * offSetX); 327 int x = 2 * _chartMargin + (i * offSetX);
280 int y = _chartCavanHeight - (innerGrade * _chartCavanHeight) + (_yLabelHeight / 2); 328 int y = _chartCavanHeight - (innerGrade * _chartCavanHeight) + (_yLabelHeight / 2);
281 - 329 +
282 // Circular point 330 // Circular point
283 if (chartData.inflexionPointStyle == PNLineChartPointStyleCircle) { 331 if (chartData.inflexionPointStyle == PNLineChartPointStyleCircle) {
284 - 332 +
285 CGRect circleRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth); 333 CGRect circleRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
286 CGPoint circleCenter = CGPointMake(circleRect.origin.x + (circleRect.size.width / 2), circleRect.origin.y + (circleRect.size.height / 2)); 334 CGPoint circleCenter = CGPointMake(circleRect.origin.x + (circleRect.size.width / 2), circleRect.origin.y + (circleRect.size.height / 2));
287 - 335 +
288 [pointPath moveToPoint:CGPointMake(circleCenter.x + (inflexionWidth / 2), circleCenter.y)]; 336 [pointPath moveToPoint:CGPointMake(circleCenter.x + (inflexionWidth / 2), circleCenter.y)];
289 [pointPath addArcWithCenter:circleCenter radius:inflexionWidth / 2 startAngle:0 endAngle:2 * M_PI clockwise:YES]; 337 [pointPath addArcWithCenter:circleCenter radius:inflexionWidth / 2 startAngle:0 endAngle:2 * M_PI clockwise:YES];
290 - 338 +
291 if ( i != 0 ) { 339 if ( i != 0 ) {
292 - 340 +
293 // calculate the point for line 341 // calculate the point for line
294 float distance = sqrt(pow(x - last_x, 2) + pow(y - last_y, 2) ); 342 float distance = sqrt(pow(x - last_x, 2) + pow(y - last_y, 2) );
295 float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x); 343 float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x);
296 float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y); 344 float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
297 float x1 = x - (inflexionWidth / 2) / distance * (x - last_x); 345 float x1 = x - (inflexionWidth / 2) / distance * (x - last_x);
298 float y1 = y - (inflexionWidth / 2) / distance * (y - last_y); 346 float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
299 - 347 +
300 [progressline moveToPoint:CGPointMake(last_x1, last_y1)]; 348 [progressline moveToPoint:CGPointMake(last_x1, last_y1)];
301 [progressline addLineToPoint:CGPointMake(x1, y1)]; 349 [progressline addLineToPoint:CGPointMake(x1, y1)];
302 } 350 }
303 - 351 +
304 last_x = x; 352 last_x = x;
305 last_y = y; 353 last_y = y;
306 } 354 }
307 // Square point 355 // Square point
308 else if (chartData.inflexionPointStyle == PNLineChartPointStyleSquare) { 356 else if (chartData.inflexionPointStyle == PNLineChartPointStyleSquare) {
309 - 357 +
310 CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth); 358 CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth);
311 CGPoint squareCenter = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2), squareRect.origin.y + (squareRect.size.height / 2)); 359 CGPoint squareCenter = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2), squareRect.origin.y + (squareRect.size.height / 2));
312 - 360 +
313 [pointPath moveToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))]; 361 [pointPath moveToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))];
314 [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))]; 362 [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))];
315 [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))]; 363 [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))];
316 [pointPath addLineToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))]; 364 [pointPath addLineToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))];
317 [pointPath closePath]; 365 [pointPath closePath];
318 - 366 +
319 if ( i != 0 ) { 367 if ( i != 0 ) {
320 - 368 +
321 // calculate the point for line 369 // calculate the point for line
322 float distance = sqrt(pow(x - last_x, 2) + pow(y - last_y, 2) ); 370 float distance = sqrt(pow(x - last_x, 2) + pow(y - last_y, 2) );
323 float last_x1 = last_x + (inflexionWidth / 2); 371 float last_x1 = last_x + (inflexionWidth / 2);
324 float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y); 372 float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y);
325 float x1 = x - (inflexionWidth / 2); 373 float x1 = x - (inflexionWidth / 2);
326 float y1 = y - (inflexionWidth / 2) / distance * (y - last_y); 374 float y1 = y - (inflexionWidth / 2) / distance * (y - last_y);
327 - 375 +
328 [progressline moveToPoint:CGPointMake(last_x1, last_y1)]; 376 [progressline moveToPoint:CGPointMake(last_x1, last_y1)];
329 [progressline addLineToPoint:CGPointMake(x1, y1)]; 377 [progressline addLineToPoint:CGPointMake(x1, y1)];
330 } 378 }
331 - 379 +
332 last_x = x; 380 last_x = x;
333 last_y = y; 381 last_y = y;
334 } 382 }
@@ -356,59 +404,30 @@ @@ -356,59 +404,30 @@
356 404
357 [progressline moveToPoint:CGPointMake(last_x1, last_y1)]; 405 [progressline moveToPoint:CGPointMake(last_x1, last_y1)];
358 [progressline addLineToPoint:CGPointMake(x1, y1)]; 406 [progressline addLineToPoint:CGPointMake(x1, y1)];
359 - } 407 + }
360 408
361 last_x = x; 409 last_x = x;
362 last_y = y; 410 last_y = y;
363 411
364 } else { 412 } else {
365 - 413 +
366 if ( i != 0 ) { 414 if ( i != 0 ) {
367 [progressline addLineToPoint:CGPointMake(x, y)]; 415 [progressline addLineToPoint:CGPointMake(x, y)];
368 } 416 }
369 - 417 +
370 [progressline moveToPoint:CGPointMake(x, y)]; 418 [progressline moveToPoint:CGPointMake(x, y)];
371 } 419 }
372 - 420 +
373 [linePointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]]; 421 [linePointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]];
374 } 422 }
375 - 423 +
376 - [_pathPoints addObject:[linePointsArray copy]]; 424 + [pathPoints addObject:[linePointsArray copy]];
377 - 425 +
378 - // setup the color of the chart line  
379 - if (chartData.color) {  
380 - chartLine.strokeColor = [chartData.color CGColor];  
381 - } else {  
382 - chartLine.strokeColor = [PNGreen CGColor];  
383 - pointLayer.strokeColor = [PNGreen CGColor];  
384 - }  
385 -  
386 - [progressline stroke];  
387 -  
388 - chartLine.path = progressline.CGPath;  
389 - pointLayer.path = pointPath.CGPath;  
390 -  
391 - [CATransaction begin];  
392 - CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];  
393 - pathAnimation.duration = 1.0;  
394 - pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];  
395 - pathAnimation.fromValue = @0.0f;  
396 - pathAnimation.toValue = @1.0f;  
397 -  
398 - [chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];  
399 - chartLine.strokeEnd = 1.0;  
400 -  
401 - // if you want cancel the point animation, conment this code, the point will show immediately  
402 - if (chartData.inflexionPointStyle != PNLineChartPointStyleNone) {  
403 - [pointLayer addAnimation:pathAnimation forKey:@"strokeEndAnimation"];  
404 - }  
405 -  
406 - [CATransaction commit];  
407 -  
408 - UIGraphicsEndImageContext();  
409 } 426 }
410 } 427 }
411 428
  429 +#pragma mark - Set Chart Data
  430 +
412 - (void)setChartData:(NSArray *)data 431 - (void)setChartData:(NSArray *)data
413 { 432 {
414 if (data != _chartData) { 433 if (data != _chartData) {
@@ -479,6 +498,13 @@ @@ -479,6 +498,13 @@
479 } 498 }
480 } 499 }
481 500
  501 +#pragma mark - Update Chart Data
  502 +
  503 +- (void)updateChartData:(NSArray *)data
  504 +{
  505 +
  506 +}
  507 +
482 #define IOS7_OR_LATER [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 508 #define IOS7_OR_LATER [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0
483 509
484 - (void)drawRect:(CGRect)rect 510 - (void)drawRect:(CGRect)rect