ifish/Ifish/controllers/HotBar/Lib/PNChart/PNCircleChart.m

269 lines
9.9 KiB
Objective-C
Executable File

//
// 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
{
self = [super initWithFrame:frame];
if (self) {
_total = total;
_current = current;
_strokeColor = PNFreshGreen;
_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, 100.0, 50.0)];
[_countingLabel setTextAlignment:NSTextAlignmentCenter];
[_countingLabel setFont:[UIFont boldSystemFontOfSize:16.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