**@interface** PieChartView : UIView
**@property** (**nonatomic**, **strong**) NSArray *dataArray;
**@property** (**nonatomic**, **strong**) NSArray *colorArray;
**@property** (**nonatomic**, **strong**) NSArray *detailTextArray;
**@property** (**nonatomic**, **strong**) NSString *title;
- (**void**)strokePath;
**@end**
**@interface** PieChartView ()
**@property** (**nonatomic**, **strong**) NSString *titleColor;
\
**@property** (**nonatomic**, **strong**) NSArray *proportionArray;
**@property** (**nonatomic**, **strong**) NSString *total;
**@property** (**nonatomic**, **strong**) UIView *centreView;
**@property** (**nonatomic**, **strong**) UILabel *titleLabel;
**@end**
\
**@implementation** PieChartView
\
- (**instancetype**)initWithFrame:(CGRect)frame
{
**self** = [**super** initWithFrame:frame];
**if** (**self**) {
}
**return** **self**;
}
\
- (**void**)handleData {
/**
计算比例*/
**self**.total = [NSString stringWithFormat:@"%.2f", [[**self**.dataArray valueForKeyPath:@"@sum.floatValue"] floatValue]];
NSMutableArray *tempArray = [NSMutableArray array];
**for** (NSNumber *number **in** **self**.dataArray) {
CGFloat numberProportion = [number floatValue]/[**self**.total floatValue];
[tempArray addObject:[NSNumber numberWithFloat:numberProportion]];
}
**self**.proportionArray = [NSArray arrayWithArray:tempArray];
}
\
- (**void**)strokePath {
// Drawing code
[**self** handleData];
CGFloat startAngle = -M_PI_2;
CGFloat endAngle = -M_PI_2;
CGFloat radius = **self**.frame.size.width/5;
CGPoint centerPoint = CGPointMake(**self**.frame.size.width/2 , **self**.frame.size.height/2);
//用来保存每段弧线夹角的中间角度和弧线中间点
NSMutableArray *pointArray = [NSMutableArray array];
NSMutableArray *centreAngleArray = [NSMutableArray array];
CGFloat current_radius = radius;
**for** (**int** i = 0; i < **self**.dataArray.count; i++ ) {
UIColor *color = **self**.colorArray[i];
NSNumber *number = **self**.proportionArray[i];
//计算弧线的绝对角度和结束角度
CGFloat angle = [number floatValue]*M_PI*2;
endAngle = startAngle + angle;
//如果该数据小于上一个数据, 半径递减
**if** (i != 0 && [number doubleValue] < [**self**.proportionArray[i-1] doubleValue]) {
current_radius = current_radius - 5;
}
//画弧线
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:centerPoint radius:current_radius startAngle:startAngle endAngle:endAngle clockwise:**YES**];
[path addLineToPoint:centerPoint];
CAShapeLayer *pieLayer = [CAShapeLayer layer];
[**self**.layer addSublayer:pieLayer];
pieLayer.fillColor = color.CGColor;
pieLayer.strokeColor = color.CGColor;
pieLayer.path = path.CGPath;
//计算弧夹角的中间角度和弧线中间点,并保存
CGFloat centreAngle = (startAngle + endAngle)/2;
CGPoint centrePoint = CGPointMake(centerPoint.x + current_radius*cos(centreAngle), centerPoint.y + current_radius*sin(centreAngle));
**if** (centreAngleArray.count) {
[centreAngleArray addObject:[NSNumber numberWithFloat:centreAngle]];
[pointArray addObject:[NSValue valueWithCGPoint:centrePoint]];
} **else** {
[centreAngleArray insertObject:[NSNumber numberWithFloat:centreAngle] atIndex:0];
[pointArray insertObject:[NSValue valueWithCGPoint:centrePoint] atIndex:0];
}
//该弧线的结束角度为下一个弧线的开始角度
startAngle = endAngle;
}
[**self** drawLineWithPointArray:pointArray centerArray:centreAngleArray];
//饼图中间空白区域
CGFloat centerViewWidth = current_radius-15;
**self**.centreView.frame = CGRectMake(0, 0, centerViewWidth*2, centerViewWidth*2);
**self**.centreView.center = centerPoint;
**self**.centreView.layer.cornerRadius = centerViewWidth;
**self**.centreView.layer.masksToBounds = **YES**;
[**self** addSubview:**self**.centreView];
//标题
**self**.titleLabel.frame = CGRectMake(0, 0, centerViewWidth*2, centerViewWidth*2);
**self**.titleLabel.text = [NSString stringWithFormat:@"%@\n%@", **self**.title, **self**.total];
[**self**.centreView addSubview:**self**.titleLabel];
}
/**
pointArray 指引线在饼图扇区的起点
centerArray 起点的角度
*/
- (**void**)drawLineWithPointArray:(NSArray *)pointArray centerArray:(NSArray *)centerArray {
//记录每一个detail文字的frame
CGRect rect = CGRectZero;
CGFloat width = **self**.bounds.size.width*0.5;
**for** (**int** i = 0; i < pointArray.count; i++) {
//指引线起点
CGPoint startPoint = [pointArray[i] CGPointValue];
CGFloat radianCenter = [centerArray[i] floatValue];
UIColor *color = **self**.colorArray[i];
NSString *proportionStr = [NSString stringWithFormat:@"%.2f%%", [**self**.proportionArray[i] doubleValue]*100];
**if** ([**self**.total doubleValue] == 0) {
proportionStr = @"";
}
NSString *text = [NSString stringWithFormat:@"%@\n%@", **self**.detailTextArray[i], proportionStr];
//指引线转折点
CGFloat turnPointTmp = 5 + i*5;
CGFloat turnPoint_X = startPoint.x + turnPointTmp *cos(radianCenter);
CGFloat turnPoint_Y = startPoint.y + turnPointTmp *sin(radianCenter);
//指引线终点
CGFloat endPoint_X = 0;
CGFloat endPoint_Y = 0;
//文字的frame数据
CGFloat titleWidth = 60;
CGFloat titleHeight = 30;
CGFloat title_X = 0;
CGFloat title_Y = turnPoint_Y;
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.alignment = NSTextAlignmentLeft;
**if** (startPoint.x <= width) {//在左边
endPoint_X = titleWidth + 15;
endPoint_Y = turnPoint_Y;
title_X = endPoint_X - titleWidth -7;
//文字靠右
paragraph.alignment = NSTextAlignmentRight;
} **else** {//在右边
endPoint_X = width*2 - (titleWidth + 15);
endPoint_Y = turnPoint_Y;
title_X = endPoint_X + 7;
}
title_Y = endPoint_Y - titleHeight/2;
//排除右边从上到下第一个(i == 0)和左边从下到上第一个(startPoint.x <= width && CGRectGetMidX(rect)> width)
**if** (i != 0 && !(startPoint.x <= width && CGRectGetMidX(rect)> width)) {//
CGRect rect1 = CGRectMake(title_X, title_Y, titleWidth, titleHeight);
CGFloat margin = 0;
**if** (CGRectIntersectsRect(rect, rect1)) {
/**两个面积是否重叠,有三种情况
1,压在上面 2、压在下面 3、包含
*/
**if** (CGRectContainsRect(rect, rect1)) {//包含
**if** (startPoint.x <= width) {//左边
margin = CGRectGetMaxY(rect1) -rect.origin.y;
endPoint_Y -= margin;
} **else** {//右边
margin = CGRectGetMaxY(rect) -rect1.origin.y;
endPoint_Y += margin;
}
} **else** {//相交
**if** (CGRectGetMaxY(rect1) > rect.origin.y && rect1.origin.y < rect.origin.y) {//rect1下半部分 与rect上半部分重叠
**if** (startPoint.x <= width) {//左边
margin = CGRectGetMaxY(rect1) - rect.origin.y;
endPoint_Y -= margin;
} **else** {//右边
margin = CGRectGetMaxY(rect) -rect1.origin.y;
endPoint_Y += margin;
}
} **else** **if** (rect1.origin.y < CGRectGetMaxY(rect) && CGRectGetMaxY(rect1) > CGRectGetMaxY(rect)) {//rect1上半部分 与rect下半部分重叠
**if** (startPoint.x <= width) {//左边
margin = CGRectGetMaxY(rect1) - rect.origin.y;
endPoint_Y -= margin;
} **else** {//右边
margin = CGRectGetMaxY(rect) -rect1.origin.y;
endPoint_Y += margin;
}
}
}
} **else** {//相离
**if** (startPoint.x <= width) {//左边
**if** (rect1.origin.y > CGRectGetMaxY(rect)) {//rect1靠下,rect靠上
margin = CGRectGetMaxY(rect1) - rect.origin.y;
endPoint_Y -= margin;
}
} **else** {//右边
**if** (CGRectGetMaxY(rect1) < rect.origin.y) {//rect靠下,rect1靠上
margin = CGRectGetMaxY(rect) -rect1.origin.y;
endPoint_Y += margin;
}
}
}
/**超出页面上下的情况 */
**if** (startPoint.x <= width) {//左边
**if** (endPoint_Y <= 0) {//
endPoint_Y = 0;
endPoint_X = CGRectGetMaxX(rect);
}
} **else** {//右边
**if** (endPoint_Y+titleHeight >= **self**.frame.size.height) {//
endPoint_Y = **self**.frame.size.height - titleHeight;
endPoint_X = rect.origin.x-titleWidth;
}
}
title_Y = endPoint_Y - titleHeight/2;
rect = CGRectMake(title_X, title_Y, titleWidth, titleHeight);
} **else** {
rect = CGRectMake(title_X, title_Y, titleWidth, titleHeight);
}
//画指引线
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(endPoint_X, endPoint_Y)];
[path addLineToPoint:CGPointMake(turnPoint_X, turnPoint_Y)];
[path addLineToPoint:startPoint];
CAShapeLayer *pieLayer = [CAShapeLayer layer];
[**self**.layer addSublayer:pieLayer];
pieLayer.fillColor = [UIColor clearColor].CGColor;
pieLayer.strokeColor = color.CGColor;
pieLayer.lineWidth = 1;
pieLayer.path = path.CGPath;
//小圆点
CGFloat dotRadius = 3;
UIView *dotView = [[UIView alloc] initWithFrame:CGRectMake(endPoint_X-dotRadius, endPoint_Y-dotRadius, dotRadius*2, dotRadius*2)];
dotView.backgroundColor = color;
dotView.layer.cornerRadius = dotRadius;
dotView.layer.masksToBounds = **YES**;
[**self** addSubview:dotView];
//画指示文字
NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:12],
NSForegroundColorAttributeName: color,
NSParagraphStyleAttributeName: paragraph};
UILabel *detailLabel = [[UILabel alloc] initWithFrame:CGRectMake(title_X, title_Y, titleWidth, titleHeight)];
detailLabel.attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes];
detailLabel.numberOfLines = 2;
[**self** addSubview:detailLabel];
}
}
\
- (UIView *)centreView {
**if** (!_centreView) {
_centreView = [[UIView alloc] init];
_centreView.backgroundColor = **self**.backgroundColor;
}
**return** _centreView;
}
\
- (UILabel *)titleLabel {
**if** (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.font = [UIFont systemFontOfSize:12];
_titleLabel.textColor = [UIColor cyanColor];
}
**return** _titleLabel;
}
\