123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- //
- // PNCircleChart.m
- // PNChartDemo
- //
- // Created by kevinzhow on 13-11-30.
- // Copyright (c) 2013年 kevinzhow. All rights reserved.
- //
- #import "PNCircleChart.h"
- @implementation PNCircleChart
- //
- //- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise {
- //
- // return [self initWithFrame:frame
- // total:total
- // current:current
- // clockwise:clockwise
- // shadow:NO
- // shadowColor:[UIColor clearColor]
- // displayCountingLabel:YES
- // overrideLineWidth:@8.0f];
- //
- //}
- //
- //- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor {
- //
- // return [self initWithFrame:frame
- // total:total
- // current:current
- // clockwise:clockwise
- // shadow:shadow
- // shadowColor:backgroundShadowColor
- // displayCountingLabel:YES
- // overrideLineWidth:@8.0f];
- //
- //}
- //
- //- (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor displayCountingLabel:(BOOL)displayCountingLabel {
- //
- // return [self initWithFrame:frame
- // total:total
- // current:current
- // clockwise:clockwise
- // shadow:shadow
- // shadowColor:backgroundShadowColor
- // displayCountingLabel:displayCountingLabel
- // overrideLineWidth:@8.0f];
- //
- //}
- - (id)initWithFrame:(CGRect)frame
- total:(NSNumber *)total
- current:(NSNumber *)current
- clockwise:(BOOL)clockwise
- shadow:(BOOL)hasBackgroundShadow
- shadowColor:(UIColor *)backgroundShadowColor
- displayCountingLabel:(BOOL)displayCountingLabel
- overrideLineWidth:(NSNumber *)overrideLineWidth
- strokeColor:(UIColor *)strokeColor
- {
- self = [super initWithFrame:frame];
- if (self) {
- _total = total;
- _current = current;
- _strokeColor = strokeColor;
- _duration = 1.0;
- _chartType = PNChartFormatTypePercent;
- _displayAnimated = YES;
-
- _displayCountingLabel = displayCountingLabel;
- CGFloat startAngle = clockwise ? -90.0f : 270.0f;
- CGFloat endAngle = clockwise ? -90.01f : 270.01f;
- _lineWidth = overrideLineWidth;
-
- UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0f, self.frame.size.height/2.0f)
- radius:(self.frame.size.height * 0.5) - ([_lineWidth floatValue]/2.0f)
- startAngle:DEGREES_TO_RADIANS(startAngle)
- endAngle:DEGREES_TO_RADIANS(endAngle)
- clockwise:clockwise];
- _circle = [CAShapeLayer layer];
- _circle.path = circlePath.CGPath;
- _circle.lineCap = kCALineCapRound;
- _circle.fillColor = [UIColor clearColor].CGColor;
- _circle.lineWidth = [_lineWidth floatValue];
- _circle.zPosition = 1;
- _circleBackground = [CAShapeLayer layer];
- _circleBackground.path = circlePath.CGPath;
- _circleBackground.lineCap = kCALineCapRound;
- _circleBackground.fillColor = [UIColor clearColor].CGColor;
- _circleBackground.lineWidth = [_lineWidth floatValue];
- _circleBackground.strokeColor = (hasBackgroundShadow ? backgroundShadowColor.CGColor : [UIColor clearColor].CGColor);
- _circleBackground.strokeEnd = 1.0;
- _circleBackground.zPosition = -1;
- [self.layer addSublayer:_circle];
- [self.layer addSublayer:_circleBackground];
- _countingLabel = [[UICountingLabel alloc] initWithFrame:CGRectMake(0, 0, 45, 30.0)];
- [_countingLabel setTextAlignment:NSTextAlignmentCenter];
- [_countingLabel setFont:[UIFont boldSystemFontOfSize:17.0f]];
- [_countingLabel setTextColor:[UIColor grayColor]];
- [_countingLabel setBackgroundColor:[UIColor clearColor]];
- [_countingLabel setCenter:CGPointMake(self.frame.size.width/2.0f, self.frame.size.height/2.0f)];
- _countingLabel.method = UILabelCountingMethodEaseInOut;
- if (_displayCountingLabel) {
- [self addSubview:_countingLabel];
- }
- }
- return self;
- }
- - (void)strokeChart
- {
- // Add counting label
- if (_displayCountingLabel) {
- NSString *format;
- switch (self.chartType) {
- case PNChartFormatTypePercent:
- format = @"%d%%";
- break;
- case PNChartFormatTypeDollar:
- format = @"$%d";
- break;
- case PNChartFormatTypeDecimal:
- format = @"%.1f";
- break;
- case PNChartFormatTypeDecimalTwoPlaces:
- format = @"%.2f";
- break;
- case PNChartFormatTypeNone:
- default:
- format = @"%d";
- break;
- }
- self.countingLabel.format = format;
- [self addSubview:self.countingLabel];
- }
- // Add circle params
- _circle.lineWidth = [_lineWidth floatValue];
- _circleBackground.lineWidth = [_lineWidth floatValue];
- _circleBackground.strokeEnd = 1.0;
- _circle.strokeColor = _strokeColor.CGColor;
- _circle.strokeEnd = [_current floatValue] / [_total floatValue];
- // Check if user wants to add a gradient from the start color to the bar color
- if (_strokeColorGradientStart) {
- // Add gradient
- self.gradientMask = [CAShapeLayer layer];
- self.gradientMask.fillColor = [[UIColor clearColor] CGColor];
- self.gradientMask.strokeColor = [[UIColor blackColor] CGColor];
- self.gradientMask.lineWidth = _circle.lineWidth;
- self.gradientMask.lineCap = kCALineCapRound;
- CGRect gradientFrame = CGRectMake(0, 0, 2*self.bounds.size.width, 2*self.bounds.size.height);
- self.gradientMask.frame = gradientFrame;
- self.gradientMask.path = _circle.path;
- CAGradientLayer *gradientLayer = [CAGradientLayer layer];
- gradientLayer.startPoint = CGPointMake(0.5,1.0);
- gradientLayer.endPoint = CGPointMake(0.5,0.0);
- gradientLayer.frame = gradientFrame;
- UIColor *endColor = (_strokeColor ? _strokeColor : [UIColor greenColor]);
- NSArray *colors = @[
- (id)endColor.CGColor,
- (id)_strokeColorGradientStart.CGColor
- ];
- gradientLayer.colors = colors;
- [gradientLayer setMask:self.gradientMask];
- [_circle addSublayer:gradientLayer];
- self.gradientMask.strokeEnd = [_current floatValue] / [_total floatValue];
- }
-
- [self addAnimationIfNeeded];
- }
- - (void)growChartByAmount:(NSNumber *)growAmount
- {
- NSNumber *updatedValue = [NSNumber numberWithFloat:[_current floatValue] + [growAmount floatValue]];
- // Add animation
- [self updateChartByCurrent:updatedValue];
- }
- -(void)updateChartByCurrent:(NSNumber *)current{
-
- [self updateChartByCurrent:current
- byTotal:_total];
-
- }
- -(void)updateChartByCurrent:(NSNumber *)current byTotal:(NSNumber *)total {
- double totalPercentageValue = [current floatValue]/([total floatValue]/100.0);
-
- if (_strokeColorGradientStart) {
- self.gradientMask.strokeEnd = _circle.strokeEnd;
- }
-
- // Add animation
- if (self.displayAnimated) {
- CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
- pathAnimation.duration = self.duration;
- pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
- pathAnimation.fromValue = @([_current floatValue] / [_total floatValue]);
- pathAnimation.toValue = @([current floatValue] / [total floatValue]);
-
- if (_strokeColorGradientStart) {
- [self.gradientMask addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
- }
- [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
-
- if (_displayCountingLabel) {
- [self.countingLabel countFrom:fmin([_current floatValue], [_total floatValue]) to:totalPercentageValue withDuration:self.duration];
- }
-
- }
- else if (_displayCountingLabel) {
- [self.countingLabel countFrom:totalPercentageValue to:totalPercentageValue withDuration:self.duration];
- }
-
- _circle.strokeEnd = [current floatValue] / [total floatValue];
- _current = current;
- _total = total;
- }
- - (void)addAnimationIfNeeded
- {
- double percentageValue = (_current.floatValue / _total.floatValue) * 100.0f;
- if (self.displayAnimated) {
- CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
- pathAnimation.duration = self.duration;
- pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
- pathAnimation.fromValue = @(0.0f);
- pathAnimation.toValue = @([_current floatValue] / [_total floatValue]);
- [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
- if(_displayCountingLabel)
- {
- [_countingLabel countFrom:0 to:percentageValue withDuration:self.duration];
- }
- if (self.gradientMask && _strokeColorGradientStart) {
- [self.gradientMask addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
- }
- }
- else {
- if (_displayCountingLabel) {
- [_countingLabel countFrom:percentageValue to:percentageValue withDuration:self.duration];
- }
- }
- }
- @end
|