新版本
This commit is contained in:
+268
@@ -0,0 +1,268 @@
|
||||
//
|
||||
// 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
|
||||
Reference in New Issue
Block a user