andi

Merge branch 'master1'

@@ -157,7 +157,7 @@ displayCountingLabel:(BOOL)displayCountingLabel @@ -157,7 +157,7 @@ displayCountingLabel:(BOOL)displayCountingLabel
157 [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; 157 [_circle addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
158 _circle.strokeEnd = [_current floatValue] / [_total floatValue]; 158 _circle.strokeEnd = [_current floatValue] / [_total floatValue];
159 159
160 - [_countingLabel countFrom:0 to:[_current floatValue] withDuration:self.duration]; 160 + [_countingLabel countFrom:0 to:[_current floatValue]/([_total floatValue]/100.0) withDuration:self.duration];
161 161
162 162
163 // Check if user wants to add a gradient from the start color to the bar color 163 // Check if user wants to add a gradient from the start color to the bar color
@@ -235,4 +235,4 @@ displayCountingLabel:(BOOL)displayCountingLabel @@ -235,4 +235,4 @@ displayCountingLabel:(BOOL)displayCountingLabel
235 _total = total; 235 _total = total;
236 } 236 }
237 237
238 -@end 238 +@end
@@ -104,6 +104,20 @@ @@ -104,6 +104,20 @@
104 } 104 }
105 } 105 }
106 106
  107 +- (CGFloat)computeEqualWidthForXLabels:(NSArray *)xLabels
  108 +{
  109 + CGFloat xLabelWidth;
  110 +
  111 + if (_showLabel) {
  112 + xLabelWidth = _chartCavanWidth / [xLabels count];
  113 + } else {
  114 + xLabelWidth = (self.frame.size.width) / [xLabels count];
  115 + }
  116 +
  117 + return xLabelWidth;
  118 +}
  119 +
  120 +
107 - (void)setXLabels:(NSArray *)xLabels 121 - (void)setXLabels:(NSArray *)xLabels
108 { 122 {
109 CGFloat xLabelWidth; 123 CGFloat xLabelWidth;
@@ -12,21 +12,24 @@ @@ -12,21 +12,24 @@
12 12
13 @interface PNPieChart() 13 @interface PNPieChart()
14 14
15 -@property (nonatomic, readwrite) NSArray *items; 15 +@property (nonatomic) NSArray *items;
16 -@property (nonatomic) CGFloat total; 16 +@property (nonatomic) NSArray *endPercentages;
17 -@property (nonatomic) CGFloat currentTotal;  
18 17
19 @property (nonatomic) CGFloat outerCircleRadius; 18 @property (nonatomic) CGFloat outerCircleRadius;
20 @property (nonatomic) CGFloat innerCircleRadius; 19 @property (nonatomic) CGFloat innerCircleRadius;
21 20
22 -@property (nonatomic) UIView *contentView; 21 +@property (nonatomic) UIView *contentView;
23 -@property (nonatomic) CAShapeLayer *pieLayer; 22 +@property (nonatomic) CAShapeLayer *pieLayer;
24 @property (nonatomic) NSMutableArray *descriptionLabels; 23 @property (nonatomic) NSMutableArray *descriptionLabels;
25 24
  25 +
26 - (void)loadDefault; 26 - (void)loadDefault;
27 27
28 - (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index; 28 - (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index;
29 - (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index; 29 - (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index;
  30 +- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index;
  31 +- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index;
  32 +- (CGFloat)ratioForItemAtIndex:(NSUInteger)index;
30 33
31 - (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius 34 - (CAShapeLayer *)newCircleLayerWithRadius:(CGFloat)radius
32 borderWidth:(CGFloat)borderWidth 35 borderWidth:(CGFloat)borderWidth
@@ -42,89 +45,86 @@ @@ -42,89 +45,86 @@
42 @implementation PNPieChart 45 @implementation PNPieChart
43 46
44 -(id)initWithFrame:(CGRect)frame items:(NSArray *)items{ 47 -(id)initWithFrame:(CGRect)frame items:(NSArray *)items{
45 - self = [self initWithFrame:frame]; 48 + self = [self initWithFrame:frame];
46 - if(self){ 49 + if(self){
47 - _items = [NSArray arrayWithArray:items]; 50 + _items = [NSArray arrayWithArray:items];
48 - _outerCircleRadius = CGRectGetWidth(self.bounds)/2; 51 + _outerCircleRadius = CGRectGetWidth(self.bounds) / 2;
49 - _innerCircleRadius = CGRectGetWidth(self.bounds)/6; 52 + _innerCircleRadius = CGRectGetWidth(self.bounds) / 6;
50 - 53 +
51 - _descriptionTextColor = [UIColor whiteColor]; 54 + _descriptionTextColor = [UIColor whiteColor];
52 - _descriptionTextFont = [UIFont fontWithName:@"Avenir-Medium" size:18.0]; 55 + _descriptionTextFont = [UIFont fontWithName:@"Avenir-Medium" size:18.0];
53 - _descriptionTextShadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; 56 + _descriptionTextShadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
54 _descriptionTextShadowOffset = CGSizeMake(0, 1); 57 _descriptionTextShadowOffset = CGSizeMake(0, 1);
55 - _duration = 1.0; 58 + _duration = 1.0;
56 59
57 - [self loadDefault]; 60 + [self loadDefault];
58 - } 61 + }
59 - 62 +
60 - return self; 63 + return self;
61 } 64 }
62 65
63 -  
64 - (void)loadDefault{ 66 - (void)loadDefault{
65 - _currentTotal = 0; 67 + __block CGFloat currentTotal = 0;
66 - _total = 0; 68 + CGFloat total = [[self.items valueForKeyPath:@"@sum.value"] floatValue];
67 - 69 + NSMutableArray *endPercentages = [NSMutableArray new];
68 - [_contentView removeFromSuperview]; 70 + [_items enumerateObjectsUsingBlock:^(PNPieChartDataItem *item, NSUInteger idx, BOOL *stop) {
69 - _contentView = [[UIView alloc] initWithFrame:self.bounds]; 71 + if (total == 0){
70 - [self addSubview:_contentView]; 72 + [endPercentages addObject:@(1.0 / _items.count * (idx + 1))];
71 - [_descriptionLabels removeAllObjects]; 73 + }else{
72 - _descriptionLabels = [NSMutableArray new]; 74 + currentTotal += item.value;
73 - 75 + [endPercentages addObject:@(currentTotal / total)];
74 - _pieLayer = [CAShapeLayer layer]; 76 + }
75 - [_contentView.layer addSublayer:_pieLayer]; 77 + }];
  78 + self.endPercentages = [endPercentages copy];
  79 +
  80 + [_contentView removeFromSuperview];
  81 + _contentView = [[UIView alloc] initWithFrame:self.bounds];
  82 + [self addSubview:_contentView];
  83 + _descriptionLabels = [NSMutableArray new];
  84 +
  85 + _pieLayer = [CAShapeLayer layer];
  86 + [_contentView.layer addSublayer:_pieLayer];
76 } 87 }
77 88
78 #pragma mark - 89 #pragma mark -
79 90
80 - (void)strokeChart{ 91 - (void)strokeChart{
81 - [self loadDefault]; 92 + [self loadDefault];
82 - 93 +
83 - [self.items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 94 + PNPieChartDataItem *currentItem;
84 - _total +=((PNPieChartDataItem *)obj).value; 95 + for (int i = 0; i < _items.count; i++) {
85 - }]; 96 + currentItem = [self dataItemForIndex:i];
86 - 97 +
87 - PNPieChartDataItem *currentItem; 98 +
88 - CGFloat currentValue = 0; 99 + CGFloat startPercnetage = [self startPercentageForItemAtIndex:i];
89 - for (int i = 0; i < _items.count; i++) { 100 + CGFloat endPercentage = [self endPercentageForItemAtIndex:i];
90 - currentItem = [self dataItemForIndex:i]; 101 +
91 - 102 + CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
92 - 103 + CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
93 - CGFloat startPercnetage = currentValue/_total; 104 + CAShapeLayer *currentPieLayer = [self newCircleLayerWithRadius:radius
94 - CGFloat endPercentage = (currentValue + currentItem.value)/_total; 105 + borderWidth:borderWidth
95 -  
96 - CAShapeLayer *currentPieLayer = [self newCircleLayerWithRadius:_innerCircleRadius + (_outerCircleRadius - _innerCircleRadius)/2  
97 - borderWidth:_outerCircleRadius - _innerCircleRadius  
98 fillColor:[UIColor clearColor] 106 fillColor:[UIColor clearColor]
99 borderColor:currentItem.color 107 borderColor:currentItem.color
100 startPercentage:startPercnetage 108 startPercentage:startPercnetage
101 endPercentage:endPercentage]; 109 endPercentage:endPercentage];
102 - [_pieLayer addSublayer:currentPieLayer]; 110 + [_pieLayer addSublayer:currentPieLayer];
103 - 111 + }
104 - currentValue+=currentItem.value; 112 +
105 - 113 + [self maskChart];
106 - } 114 +
107 -  
108 - [self maskChart];  
109 -  
110 - currentValue = 0;  
111 for (int i = 0; i < _items.count; i++) { 115 for (int i = 0; i < _items.count; i++) {
112 - currentItem = [self dataItemForIndex:i]; 116 + UILabel *descriptionLabel = [self descriptionLabelForItemAtIndex:i];
113 - UILabel *descriptionLabel = [self descriptionLabelForItemAtIndex:i]; 117 + [_contentView addSubview:descriptionLabel];
114 - [_contentView addSubview:descriptionLabel];  
115 - currentValue+=currentItem.value;  
116 [_descriptionLabels addObject:descriptionLabel]; 118 [_descriptionLabels addObject:descriptionLabel];
117 - } 119 + }
118 } 120 }
119 121
120 - (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index{ 122 - (UILabel *)descriptionLabelForItemAtIndex:(NSUInteger)index{
121 - PNPieChartDataItem *currentDataItem = [self dataItemForIndex:index]; 123 + PNPieChartDataItem *currentDataItem = [self dataItemForIndex:index];
122 CGFloat distance = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2; 124 CGFloat distance = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
123 - CGFloat centerPercentage =(_currentTotal + currentDataItem.value /2 ) / _total; 125 + CGFloat centerPercentage = ([self startPercentageForItemAtIndex:index] + [self endPercentageForItemAtIndex:index])/ 2;
124 CGFloat rad = centerPercentage * 2 * M_PI; 126 CGFloat rad = centerPercentage * 2 * M_PI;
125 127
126 - _currentTotal += currentDataItem.value;  
127 -  
128 UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 80)]; 128 UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];
129 NSString *titleText = currentDataItem.textDescription; 129 NSString *titleText = currentDataItem.textDescription;
130 NSString *titleValue; 130 NSString *titleValue;
@@ -141,28 +141,44 @@ @@ -141,28 +141,44 @@
141 NSString* str = [titleValue stringByAppendingString:[NSString stringWithFormat:@"\n%@",titleText]]; 141 NSString* str = [titleValue stringByAppendingString:[NSString stringWithFormat:@"\n%@",titleText]];
142 descriptionLabel.text = str ; 142 descriptionLabel.text = str ;
143 } 143 }
  144 + descriptionLabel.text = titleText;
144 145
145 CGPoint center = CGPointMake(_outerCircleRadius + distance * sin(rad), 146 CGPoint center = CGPointMake(_outerCircleRadius + distance * sin(rad),
146 _outerCircleRadius - distance * cos(rad)); 147 _outerCircleRadius - distance * cos(rad));
147 148
148 descriptionLabel.font = _descriptionTextFont; 149 descriptionLabel.font = _descriptionTextFont;
149 CGSize labelSize = [descriptionLabel.text sizeWithAttributes:@{NSFontAttributeName:descriptionLabel.font}]; 150 CGSize labelSize = [descriptionLabel.text sizeWithAttributes:@{NSFontAttributeName:descriptionLabel.font}];
150 - descriptionLabel.frame = CGRectMake( 151 + descriptionLabel.frame = CGRectMake(descriptionLabel.frame.origin.x, descriptionLabel.frame.origin.y,
151 - descriptionLabel.frame.origin.x, descriptionLabel.frame.origin.y, 152 + descriptionLabel.frame.size.width, labelSize.height);
152 - descriptionLabel.frame.size.width, labelSize.height); 153 + descriptionLabel.numberOfLines = 0;
153 - descriptionLabel.numberOfLines = 0; 154 + descriptionLabel.textColor = _descriptionTextColor;
154 - descriptionLabel.textColor = _descriptionTextColor; 155 + descriptionLabel.shadowColor = _descriptionTextShadowColor;
155 - descriptionLabel.shadowColor = _descriptionTextShadowColor; 156 + descriptionLabel.shadowOffset = _descriptionTextShadowOffset;
156 - descriptionLabel.shadowOffset = _descriptionTextShadowOffset; 157 + descriptionLabel.textAlignment = NSTextAlignmentCenter;
157 - descriptionLabel.textAlignment = NSTextAlignmentCenter; 158 + descriptionLabel.center = center;
158 - descriptionLabel.center = center; 159 + descriptionLabel.alpha = 0;
159 - descriptionLabel.alpha = 0;  
160 descriptionLabel.backgroundColor = [UIColor clearColor]; 160 descriptionLabel.backgroundColor = [UIColor clearColor];
161 - return descriptionLabel; 161 + return descriptionLabel;
162 } 162 }
163 163
164 - (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index{ 164 - (PNPieChartDataItem *)dataItemForIndex:(NSUInteger)index{
165 - return self.items[index]; 165 + return self.items[index];
  166 +}
  167 +
  168 +- (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index{
  169 + if(index == 0){
  170 + return 0;
  171 + }
  172 +
  173 + return [_endPercentages[index - 1] floatValue];
  174 +}
  175 +
  176 +- (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index{
  177 + return [_endPercentages[index] floatValue];
  178 +}
  179 +
  180 +- (CGFloat)ratioForItemAtIndex:(NSUInteger)index{
  181 + return [self endPercentageForItemAtIndex:index] - [self startPercentageForItemAtIndex:index];
166 } 182 }
167 183
168 #pragma mark private methods 184 #pragma mark private methods
@@ -190,38 +206,42 @@ @@ -190,38 +206,42 @@
190 circle.lineWidth = borderWidth; 206 circle.lineWidth = borderWidth;
191 circle.path = path.CGPath; 207 circle.path = path.CGPath;
192 208
193 - 209 + return circle;
194 - return circle;  
195 } 210 }
196 211
197 - (void)maskChart{ 212 - (void)maskChart{
198 - CAShapeLayer *maskLayer = [self newCircleLayerWithRadius:_innerCircleRadius + (_outerCircleRadius - _innerCircleRadius)/2 213 + CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2;
199 - borderWidth:_outerCircleRadius - _innerCircleRadius 214 + CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius;
  215 + CAShapeLayer *maskLayer = [self newCircleLayerWithRadius:radius
  216 + borderWidth:borderWidth
200 fillColor:[UIColor clearColor] 217 fillColor:[UIColor clearColor]
201 borderColor:[UIColor blackColor] 218 borderColor:[UIColor blackColor]
202 startPercentage:0 219 startPercentage:0
203 endPercentage:1]; 220 endPercentage:1];
204 - 221 +
205 - _pieLayer.mask = maskLayer; 222 + _pieLayer.mask = maskLayer;
206 - CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 223 + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
207 - animation.duration = _duration; 224 + animation.duration = _duration;
208 - animation.fromValue = @0; 225 + animation.fromValue = @0;
209 - animation.toValue = @1; 226 + animation.toValue = @1;
210 animation.delegate = self; 227 animation.delegate = self;
211 - animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 228 + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
212 - animation.removedOnCompletion = YES; 229 + animation.removedOnCompletion = YES;
213 - [maskLayer addAnimation:animation forKey:@"circleAnimation"]; 230 + [maskLayer addAnimation:animation forKey:@"circleAnimation"];
214 } 231 }
215 232
216 -- (void)createArcAnimationForLayer:(CAShapeLayer *)layer ForKey:(NSString *)key fromValue:(NSNumber *)from toValue:(NSNumber *)to Delegate:(id)delegate 233 +- (void)createArcAnimationForLayer:(CAShapeLayer *)layer
217 -{ 234 + forKey:(NSString *)key
218 - CABasicAnimation *arcAnimation = [CABasicAnimation animationWithKeyPath:key]; 235 + fromValue:(NSNumber *)from
219 - arcAnimation.fromValue = @0; 236 + toValue:(NSNumber *)to
220 - [arcAnimation setToValue:to]; 237 + delegate:(id)delegate{
221 - [arcAnimation setDelegate:delegate]; 238 + CABasicAnimation *arcAnimation = [CABasicAnimation animationWithKeyPath:key];
222 - [arcAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]]; 239 + arcAnimation.fromValue = @0;
223 - [layer addAnimation:arcAnimation forKey:key]; 240 + arcAnimation.toValue = to;
224 - [layer setValue:to forKey:key]; 241 + arcAnimation.delegate = delegate;
  242 + arcAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
  243 + [layer addAnimation:arcAnimation forKey:key];
  244 + [layer setValue:to forKey:key];
225 } 245 }
226 246
227 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ 247 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
@@ -27,4 +27,11 @@ @@ -27,4 +27,11 @@
27 return item; 27 return item;
28 } 28 }
29 29
  30 +- (void)setValue:(CGFloat)value{
  31 + NSAssert(value >= 0, @"value should >= 0");
  32 + if (value != _value){
  33 + _value = value;
  34 + }
  35 +}
  36 +
30 @end 37 @end
@@ -156,6 +156,24 @@ @@ -156,6 +156,24 @@
156 } 156 }
157 } 157 }
158 158
  159 +- (NSArray*) getAxisMinMax:(NSArray*)xValues
  160 +{
  161 + float min = [xValues[0] floatValue];
  162 + float max = [xValues[0] floatValue];
  163 + for (NSNumber *number in xValues)
  164 + {
  165 + if ([number floatValue] > max)
  166 + max = [number floatValue];
  167 +
  168 + if ([number floatValue] < min)
  169 + min = [number floatValue];
  170 + }
  171 + NSArray *result = @[[NSNumber numberWithFloat:min], [NSNumber numberWithFloat:max]];
  172 +
  173 +
  174 + return result;
  175 +}
  176 +
159 - (void)setAxisXLabel:(NSArray *)array { 177 - (void)setAxisXLabel:(NSArray *)array {
160 if(array.count == ++_AxisX_partNumber){ 178 if(array.count == ++_AxisX_partNumber){
161 [_axisX_labels removeAllObjects]; 179 [_axisX_labels removeAllObjects];