饼状图(带有指引线)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/st646889325/article/details/82588736

#import <UIKit/UIKit.h>

@interface YTLPieView : UIView

/**

数据统计饼图

@param frame frame

@param dataItems 每个部分的数据源

@param colorItems 每个部分的颜色

@param upTextItems 线上文字

@param downTextItems 线下文字

*/

- (instancetype)initWithFrame:(CGRect)frame

                    dataItems:(NSArray *)dataItems

                   colorItems:(NSArray *)colorItems

                  upTextItems:(NSArray *)upTextItems

                downTextItems:(NSArray *)downTextItems;

@end

#import "YTLPieView.h"

#import "UIView+Extend.h"

#import "Masonry.h"

@interface YTLPieView ()

@property (nonatomic, strong) NSArray *dataItems;

@property (nonatomic, strong) NSArray *colorItems;

@property (nonatomic, strong) NSArray *upTextItems;

@property (nonatomic, strong) NSArray *downTextItems;

@property (nonatomic, assign) CGFloat animationTime;

// 外环半径

@property (nonatomic, assign) CGFloat pieR;

// 环形的宽度

@property (nonatomic, assign) CGFloat pieW;

// 圆心

@property (nonatomic, assign) CGPoint pieCenter;

@end

@implementation YTLPieView

- (instancetype)initWithFrame:(CGRect)frame

                    dataItems:(NSArray *)dataItems

                   colorItems:(NSArray *)colorItems

                  upTextItems:(NSArray *)upTextItems

                downTextItems:(NSArray *)downTextItems

{

    self = [super initWithFrame:frame];

    if (self) {

        

        self.backgroundColor = [UIColor blackColor];

        

        self.dataItems = dataItems;

        self.colorItems = colorItems;

        self.upTextItems = upTextItems;

        self.downTextItems = downTextItems;

        

        self.animationTime = 1;

        self.pieR = self.height * 0.25;

        self.pieW = self.pieR - self.pieR/6.0;

        self.pieCenter = CGPointMake(self.width/2, self.height/2);

    }

    return self;

}

- (void)drawRect:(CGRect)rect

{

    // 数组求和

    CGFloat max = [[self.dataItems valueForKeyPath:@"@sum.floatValue"] floatValue];

    

    CGFloat startAngle = -M_PI_2;

    for (int i = 0; i < self.dataItems.count; i++)

    {

        // 扇形部分

        CAShapeLayer *layer = [CAShapeLayer layer];

        layer.fillColor = [UIColor clearColor].CGColor;

        layer.strokeColor = [self.colorItems[i] CGColor];

        layer.lineWidth = self.pieW;

        [self.layer addSublayer:layer];

        CGFloat endAngle = [self.dataItems[i] floatValue]/max * (2*M_PI) + startAngle;

        UIBezierPath *layerPath = [UIBezierPath bezierPathWithArcCenter:self.pieCenter radius:self.pieR startAngle:startAngle endAngle:endAngle clockwise:YES];

        layer.path = layerPath.CGPath;

        

        

        

        // 小圆点数据

        CGPoint minPieCenter;// 小圆点中心

        CGFloat picOutR = self.pieR + self.pieW/2.0 + 10;// 外层半径

        CGFloat middleAngle = startAngle + (endAngle - startAngle)/2.0;// 扇形中间点角度

        

        

        // 折线数据

        CGPoint line_1_Point;// 转折点

        CGPoint line_2_Point;// 终点

        CGFloat line_1_W = 10;// 1线宽

        CGFloat lineSpace = 15;// 终点距两边的距离

        CGFloat lineAngle = M_PI_2/2;// 短线偏移角度

        

        if (middleAngle >= -M_PI_2 && middleAngle <= 0)

        {// 1

            CGFloat angle = 0 - middleAngle;

            minPieCenter = CGPointMake(self.pieCenter.x + cosf(angle)*picOutR, self.pieCenter.y - sinf(angle)*picOutR);

            

            

            if (angle > -M_PI_2/2)

            {

                lineAngle = M_PI_2/3;

            }

            line_1_Point = CGPointMake(minPieCenter.x + cosf(lineAngle)*line_1_W, minPieCenter.y - sinf(lineAngle)*line_1_W);

            line_2_Point = CGPointMake(self.width - lineSpace, line_1_Point.y);

        }else if (middleAngle >= 0 && middleAngle <= M_PI_2)

        {// 4

            minPieCenter = CGPointMake(self.pieCenter.x + cosf(middleAngle)*picOutR, self.pieCenter.y + sinf(middleAngle)*picOutR);

            

            

            if (middleAngle > M_PI_2/2)

            {

                lineAngle = M_PI_2/3;

            }

            line_1_Point = CGPointMake(minPieCenter.x + cosf(lineAngle)*line_1_W, minPieCenter.y + sinf(lineAngle)*line_1_W);

            line_2_Point = CGPointMake(self.width - lineSpace, line_1_Point.y);

        }else if (middleAngle >= M_PI_2 && middleAngle <= 2*M_PI_2)

        {// 3

            CGFloat angle = M_PI - middleAngle;

            minPieCenter = CGPointMake(self.pieCenter.x - cosf(angle)*picOutR, self.pieCenter.y + sinf(angle)*picOutR);

            

            

            if (middleAngle < 3*M_PI_2/2)

            {

                lineAngle = M_PI_2/3;

            }

            line_1_Point = CGPointMake(minPieCenter.x - cosf(lineAngle)*line_1_W, minPieCenter.y + sinf(lineAngle)*line_1_W);

            line_2_Point = CGPointMake(lineSpace, line_1_Point.y);

        }else

        {// 2

            CGFloat angle = middleAngle - M_PI;

            minPieCenter = CGPointMake(self.pieCenter.x - cosf(angle)*picOutR, self.pieCenter.y - sinf(angle)*picOutR);

            

            

            if (middleAngle > 5*M_PI_2/2)

            {

                lineAngle = M_PI_2/3;

            }

            line_1_Point = CGPointMake(minPieCenter.x - cosf(lineAngle)*line_1_W, minPieCenter.y - sinf(lineAngle)*line_1_W);

            line_2_Point = CGPointMake(lineSpace, line_1_Point.y);

        }

        

        

        // 圆点

        CAShapeLayer *minLayer = [CAShapeLayer layer];

        //minLayer.fillColor = [self.colorItems[i] CGColor];

         minLayer.fillColor = [UIColor whiteColor].CGColor;

        [self.layer addSublayer:minLayer];

        UIBezierPath *minPath = [UIBezierPath bezierPathWithArcCenter:minPieCenter radius:0 startAngle:-M_PI_2 endAngle:3*M_PI_2 clockwise:YES];

        minLayer.path = minPath.CGPath;

        

        

        // 折线

        CAShapeLayer *lineLayer = [CAShapeLayer layer];

        //lineLayer.strokeColor = [self.colorItems[i] CGColor];

        lineLayer.strokeColor = [UIColor whiteColor].CGColor;

        lineLayer.fillColor = [UIColor clearColor].CGColor;

        [self.layer addSublayer:lineLayer];

        

        UIBezierPath *linePath = [UIBezierPath bezierPath];

        [linePath moveToPoint:minPieCenter];

        [linePath addLineToPoint:line_1_Point];

        [linePath addLineToPoint:line_2_Point];

        

        lineLayer.path = linePath.CGPath;

        

        CABasicAnimation *lineAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];

        lineAnimation.duration = self.animationTime;

        lineAnimation.repeatCount = 1;

        lineAnimation.fromValue = @(0);

        lineAnimation.toValue = @(1);

        lineAnimation.removedOnCompletion = NO;

        lineAnimation.fillMode = kCAFillModeForwards;

        lineAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

        [lineLayer addAnimation:lineAnimation forKey:nil];

        

        UILabel *upLabel = nil;

        UILabel *downLabel = nil;

        // 线上的文字

        if (i < self.upTextItems.count)

        {

            upLabel = [self createLabel:self.upTextItems[i] endPoint:line_2_Point isUp:YES];

        }

        

        // 线下的文字

        if (i < self.downTextItems.count)

        {

            downLabel = [self createLabel:self.downTextItems[i] endPoint:line_2_Point isUp:NO];

        }

        

        [UIView animateWithDuration:self.animationTime animations:^{

            upLabel.alpha = 1;

            downLabel.alpha = 1;

        }];

        

        startAngle = endAngle;

    }

    

    

    // 遮盖的圆

    CAShapeLayer *backLayer = [CAShapeLayer layer];

    backLayer.fillColor = [UIColor clearColor].CGColor;

    backLayer.strokeColor = self.backgroundColor.CGColor;

    backLayer.lineWidth = self.pieW + 5;

    

    UIBezierPath *backLayerPath = [UIBezierPath bezierPathWithArcCenter:self.pieCenter radius:self.pieR startAngle:-M_PI_2 endAngle:3 * M_PI_2 clockwise:YES];

    backLayer.path = backLayerPath.CGPath;

    

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];

    animation.duration = self.animationTime;

    animation.repeatCount = 1;

    animation.fromValue = @(0);

    animation.toValue = @(1);

    animation.removedOnCompletion = NO;

    animation.fillMode = kCAFillModeForwards;

    [backLayer addAnimation:animation forKey:nil];

    [self.layer addSublayer:backLayer];

}

- (UILabel *)createLabel:(NSString *)text endPoint:(CGPoint)endPoint isUp:(BOOL)isUp

{

    UILabel *label = [[UILabel alloc] init];

    label.textColor = [UIColor whiteColor];

    label.font = [UIFont systemFontOfSize:14];

    label.text = text;

    label.alpha = 0;

    [self addSubview:label];

    

    if (endPoint.x > self.width/2)

    {

        label.textAlignment = NSTextAlignmentRight;

    }

    

    if (isUp)

    {// 线上

        [label mas_makeConstraints:^(MASConstraintMaker *make) {

            

            make.height.mas_equalTo(15);

            make.bottom.mas_equalTo( - (self.height - endPoint.y) - 5);

            

            if (endPoint.x > self.width/2)

            {

                make.right.mas_equalTo( - (self.width - endPoint.x));

            }else

            {

                make.left.mas_equalTo(endPoint.x);

            }

        }];

    }else

    {// 线下

        [label mas_makeConstraints:^(MASConstraintMaker *make) {

            

            make.height.mas_equalTo(15);

            make.top.mas_equalTo(endPoint.y + 5);

            

            if (endPoint.x > self.width/2)

            {

                make.right.mas_equalTo( - (self.width - endPoint.x));

            }else

            {

                make.left.mas_equalTo(endPoint.x);

            }

        }];

    }

    

    return label;

}

@end

猜你喜欢

转载自blog.csdn.net/st646889325/article/details/82588736
今日推荐