Zhang Hang

PieChart divides equally when all value of data items are 0

... ... @@ -11,8 +11,7 @@
@interface PNPieChart()
@property (nonatomic, readwrite) NSArray *items;
@property (nonatomic) CGFloat total;
@property (nonatomic) CGFloat currentTotal;
@property (nonatomic) NSArray *endPercentages;
@property (nonatomic) CGFloat outerCircleRadius;
@property (nonatomic) CGFloat innerCircleRadius;
... ... @@ -21,11 +20,14 @@
@property (nonatomic) CAShapeLayer *pieLayer;
@property (nonatomic) NSMutableArray *descriptionLabels;
- (void)loadDefault;
- (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index;
- (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index;
- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index;
- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index;
- (CGFloat)ratioForItemAtIndex:(NSUInteger)index;
- (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
borderWidth:(CGFloat)borderWidth
fillColor:(UIColor *)fillColor
... ... @@ -58,15 +60,23 @@
return self;
}
- (void)loadDefault{
_currentTotal = 0;
_total = 0;
__block CGFloat currentTotal = 0;
CGFloat total = [[self.items valueForKeyPath:@"@sum.value"] floatValue];
NSMutableArray *endPercentages = [NSMutableArray new];
[_items enumerateObjectsUsingBlock:^(PNPieChartDataItem *item, NSUInteger idx, BOOL *stop) {
if (total == 0){
[endPercentages addObject:@(1.0/_items.count*(idx+1))];
}else{
currentTotal += item.value;
[endPercentages addObject:@(currentTotal/total)];
}
}];
self.endPercentages = [endPercentages copy];
[_contentView removeFromSuperview];
_contentView = [[UIView alloc] initWithFrame:self.bounds];
[self addSubview:_contentView];
[_descriptionLabels removeAllObjects];
_descriptionLabels = [NSMutableArray new];
_pieLayer = [CAShapeLayer layer];
... ... @@ -78,39 +88,30 @@
- (void)strokeChart{
[self loadDefault];
[self.items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
_total +=((PNPieChartDataItem *)obj).value;
}];
PNPieChartDataItem *currentItem;
CGFloat currentValue = 0;
for (int i = 0; i < _items.count; i++) {
currentItem = [self dataItemForIndex:i];
CGFloat startPercnetage = currentValue/_total;
CGFloat endPercentage = (currentValue + currentItem.value)/_total;
CGFloat startPercnetage = [self startPercentageForItemAtIndex:i];
CGFloat endPercentage = [self endPercentageForItemAtIndex:i];
CAShapeLayer *currentPieLayer = [self newCircleLayerWithRadius:_innerCircleRadius + (_outerCircleRadius - _innerCircleRadius)/2
borderWidth:_outerCircleRadius - _innerCircleRadius
CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius)/2;
CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
CAShapeLayer *currentPieLayer = [self newCircleLayerWithRadius:radius
borderWidth:borderWidth
fillColor:[UIColor clearColor]
borderColor:currentItem.color
startPercentage:startPercnetage
endPercentage:endPercentage];
[_pieLayer addSublayer:currentPieLayer];
currentValue+=currentItem.value;
}
[self maskChart];
currentValue = 0;
for (int i = 0; i < _items.count; i++) {
currentItem = [self dataItemForIndex:i];
UILabel *descriptionLabel = [self descriptionLabelForItemAtIndex:i];
[_contentView addSubview:descriptionLabel];
currentValue+=currentItem.value;
[_descriptionLabels addObject:descriptionLabel];
}
}
... ... @@ -118,19 +119,17 @@
- (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index{
PNPieChartDataItem *currentDataItem = [self dataItemForIndex:index];
CGFloat distance = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
CGFloat centerPercentage =(_currentTotal + currentDataItem.value /2 ) / _total;
CGFloat centerPercentage = ([self startPercentageForItemAtIndex:index] + [self endPercentageForItemAtIndex:index])/2;
CGFloat rad = centerPercentage * 2 * M_PI;
_currentTotal += currentDataItem.value;
UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
NSString *titleText = currentDataItem.textDescription;
if(!titleText){
titleText = [NSString stringWithFormat:@"%.0f%%",currentDataItem.value/ _total * 100];
titleText = [NSString stringWithFormat:@"%.0f%%",[self ratioForItemAtIndex:index] * 100];
descriptionLabel.text = titleText ;
}
else {
NSString* str = [NSString stringWithFormat:@"%.0f%%\n",currentDataItem.value/ _total * 100];
NSString* str = [NSString stringWithFormat:@"%.0f%%\n",[self ratioForItemAtIndex:index] * 100];
str = [str stringByAppendingString:titleText];
descriptionLabel.text = str ;
}
... ... @@ -158,6 +157,22 @@
return self.items[index];
}
- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index{
if(index == 0){
return 0;
}
return [_endPercentages[index - 1] floatValue];
}
- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index{
return [_endPercentages[index] floatValue];
}
- (CGFloat)ratioForItemAtIndex:(NSUInteger)index{
return [self endPercentageForItemAtIndex:index] - [self startPercentageForItemAtIndex:index];
}
#pragma mark private methods
- (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
... ... @@ -188,8 +203,10 @@
}
- (void)maskChart{
CAShapeLayer *maskLayer = [self newCircleLayerWithRadius:_innerCircleRadius + (_outerCircleRadius - _innerCircleRadius)/2
borderWidth:_outerCircleRadius - _innerCircleRadius
CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius)/2;
CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
CAShapeLayer *maskLayer = [self newCircleLayerWithRadius:radius
borderWidth:borderWidth
fillColor:[UIColor clearColor]
borderColor:[UIColor blackColor]
startPercentage:0
... ...