你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS 餅狀圖的封裝與實現

iOS 餅狀圖的封裝與實現

編輯:IOS開發綜合

有時候我們在處理一些數據的時候,需要用到柱狀圖,折線圖和餅狀圖等來呈現數據,讓用戶能夠對數據更加清晰明了化。下面我們來看一下簡單的餅狀圖的實現。

延展

#import "NSObject+XuSong.h"
**NSObject+XuSong.h**
/**
 *  N秒後執行動作(不阻塞主線程)
 *
 *  @param seconds 幾秒
 *  @param actions 幾秒後執行的動作
 */
    - (void)dispatch_after_withSeconds:(float)seconds actions:(void(^)(void))actions;

**NSObject+XuSong.m**
- (void)dispatch_after_withSeconds:(float)seconds actions:(void(^)(void))actions{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(seconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    actions();
});

#import "NSString+XuSong.h"
**NSString+XuSong.h**
    /**
 *  計算字符串寬度(指當該字符串放在view時的自適應寬度)
 *
 *  @param size 填入預留的大小
 *  @param font 字體大小
 *
 *  @return 返回CGRect
 */
- (CGRect)stringWidthRectWithSize:(CGSize)size fontOfSize:(CGFloat)font;

**NSString+XuSong.m**
- (CGRect)stringWidthRectWithSize:(CGSize)size fontOfSize:(CGFloat)font{
NSDictionary * attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:font]};

return [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
}

#import "UIColor+XuSong.h"
**UIColor+XuSong.h**
@interface UIColor (XuSong)
@property (nonatomic, assign, readonly) CGFloat red;
@property (nonatomic, assign, readonly) CGFloat green;
@property (nonatomic, assign, readonly) CGFloat blue;
@property (nonatomic, assign, readonly) CGFloat alpha;
@end

**UIColor+XuSong.m**
@implementation UIColor (XuSong)
- (NSDictionary *)getRGBDictionaryByColor{
    CGFloat r=0,g=0,b=0,a=0;
    if ([self respondsToSelector:@selector(getRed:green:blue:alpha:)]) {
        [self getRed:&r green:&g blue:&b alpha:&a];
    }
    else {
        const CGFloat *components = CGColorGetComponents(self.CGColor);
        r = components[0];
        g = components[1];
        b = components[2];
        a = components[3];
    }

    r = r * 255;
    g = g * 255;
    b = b * 255;

    return @{@"R":@(r),
             @"G":@(g),
             @"B":@(b),
             @"A":@(a)};
}

- (CGFloat)red{
    NSDictionary * dict = [self getRGBDictionaryByColor];
    return [dict[@"R"] floatValue];
}

- (CGFloat)green{
    NSDictionary * dict = [self getRGBDictionaryByColor];
    return [dict[@"G"] floatValue];
}

- (CGFloat)blue{
    NSDictionary * dict = [self getRGBDictionaryByColor];
    return [dict[@"B"] floatValue];
}

- (CGFloat)alpha{
    NSDictionary * dict = [self getRGBDictionaryByColor];
    return [dict[@"A"] floatValue];
}
@end

#import "UIView+XuSong.h"
**UIView+XuSong.h**
/**
 *  自定義邊框
 *
 *  @param cornerRadius 角落半徑
 *  @param borderWidth  邊框寬度
 *  @param color        邊框顏色
 */
-(void)setBorderCornerRadius:(CGFloat)cornerRadius andBorderWidth:(CGFloat)borderWidth andBorderColor:(UIColor *)color;

**UIView+XuSong.m**
-(void)setBorderCornerRadius:(CGFloat)cornerRadius andBorderWidth:(CGFloat)borderWidth andBorderColor:(UIColor *)color{
self.layer.cornerRadius = cornerRadius;
self.layer.borderWidth = borderWidth;
self.layer.borderColor = color.CGColor;
}

頭文件

**ZFChart.h**
#import "ZFConst.h"
#import "ZFPieChart.h"
#import "ZFColor.h"
**ZFColor.h**
#define ZFBlack [UIColor blackColor]
#define ZFDarkGray [UIColor darkGrayColor]
#define ZFLightGray [UIColor lightGrayColor]
#define ZFWhite [UIColor whiteColor]
#define ZFGray [UIColor grayColor]
#define ZFRed [UIColor redColor]
#define ZFGreen [UIColor greenColor]
#define ZFBlue [UIColor blueColor]
#define ZFCyan [UIColor cyanColor]
#define ZFYellow [UIColor yellowColor]
#define ZFMagenta [UIColor magentaColor]
#define ZFOrange [UIColor orangeColor]
#define ZFPurple [UIColor purpleColor]
#define ZFBrown [UIColor brownColor]
#define ZFClear [UIColor clearColor]
**ZFConst.h**
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
#define ADAPTATION_WIDTH7(Width) [UIScreen mainScreen].bounds.size.width * (Width) / 375
#define IMGNAME(name) [UIImage imageNamed:name]
/**
 *  直接填寫小數
 */
#define ZFDecimalColor(r, g, b, a) [UIColor colorWithRed:r green:g blue:b alpha:a]

/**
 *  直接填寫整數
 */
#define ZFColor(r, g, b, a) [UIColor colorWithRed:r / 255.f green:g / 255.f blue:b / 255.f alpha:a]

/**
 *  隨機顏色
 */
#define ZFRandomColor ZFColor(arc4random() % 256, arc4random() % 256, arc4random() % 256, 1)

#define NAVIGATIONBAR_HEIGHT 64.f
#define TABBAR_HEIGHT 49.f

/**
 *  角度求三角函數sin值
 *  @param a 角度
 */
#define ZFSin(a) sin(a / 180.f * M_PI)

/**
 *  角度求三角函數cos值
 *  @param a 角度
 */
#define ZFCos(a) cos(a / 180.f * M_PI)

/**
 *  角度求三角函數tan值
 *  @param a 角度
 */
#define ZFTan(a) tan(a / 180.f * M_PI)

/**
 *  弧度轉角度
 *  @param radian 弧度
 */
#define ZFAngle(radian) (radian / M_PI * 180.f)

/**
 *  角度轉弧度
 *  @param angle 角度
 */
#define ZFRadian(angle) (angle / 180.f * M_PI)

/**
 *  坐標軸起點x值
 */
#define ZFAxisLineStartXPos 50.f

/**
 *  y軸label tag值
 */
#define YLineValueLabelTag 100

/**
 *  x軸item寬度
 */
#define XLineItemWidth 25.f

/**
 *  x軸item間隔
 */
#define XLineItemGapLength 20.f


#warning message - 此屬性最好不要隨意修改
/**
 *  坐標y軸最大上限值到箭頭的間隔距離 (此屬性最好不要隨意修改)
 */
#define ZFAxisLineGapFromYLineMaxValueToArrow 20.f

畫線和動畫效果

#import “ZFTranslucencePath.h”

**ZFTranslucencePath.h**
    #import 
    #import 

    @interface ZFTranslucencePath : CAShapeLayer

    + (instancetype)layerWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

    - (instancetype)initWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
    @end

    **ZFTranslucencePath.m**
    @implementation ZFTranslucencePath

    + (instancetype)layerWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise{
        return [[ZFTranslucencePath alloc] initWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:clockwise];
    }

    - (instancetype)initWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise{
        self = [super init];
        if (self) {
            self.fillColor = nil;
            self.opacity = 0.5f;
            self.path = [self translucencePathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:clockwise].CGPath;
        }
        return self;
    }

    - (UIBezierPath *)translucencePathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise{
        UIBezierPath * bezierPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:clockwise];
        return bezierPath;
    }
    @end

主視圖

#import “ZFPieChart.h”

**ZFPieChart.h**

#import 
typedef enum{
    /**
     *  保留2位小數形式(默認)
     */
    kPercentTypeDecimal = 0,
    /**
     *  取整數形式(四捨五入)
     */
    kPercentTypeInteger = 1
}kPercentType;

@interface ZFPieChart : UIView

/** 標題 */
@property (nonatomic, copy) NSString * title;
/** 數值數組 (存儲的是NSString類型) */
@property (nonatomic, strong) NSMutableArray * valueArray;
/** 名字數組 (存儲的是NSString類型) */
@property (nonatomic, strong) NSMutableArray * nameArray;
/** 顏色數組 (存儲的是UIColor類型) */
@property (nonatomic, strong) NSMutableArray * colorArray;
/** kPercentType類型 */
@property (nonatomic, assign) kPercentType percentType;
/** 顯示詳細信息(默認為YES) */
@property (nonatomic, assign) BOOL isShowDetail;
/** 顯示百分比(默認為YES) */
@property (nonatomic, assign) BOOL isShowPercent;

#pragma mark - public method

/**
 *  重繪
 */
- (void)strokePath;

@end

**ZFPieChart.m**

#import "ZFPieChart.h"
#import "ZFConst.h"
#import "NSObject+XuSong.h"
#import "NSString+XuSong.h"
#import "UIColor+XuSong.h"
#import "UIView+XuSong.h"
#import "ZFTranslucencePath.h"
#import "Masonry.h"

#define PercentLabelTag 100
#define DetailBackgroundTag 500

@interface ZFPieChart()

/** 總數 */
@property (nonatomic, assign) CGFloat totalValue;
/** 半徑 */
@property (nonatomic, assign) CGFloat radius;
/** 半徑最大上限 */
@property (nonatomic, assign) CGFloat maxRadius;
/** 記錄每個圓弧開始的角度 */
@property (nonatomic, assign) CGFloat startAngle;
/** 動畫總時長 */
@property (nonatomic, assign) CFTimeInterval totalDuration;
/** 圓環線寬 */
@property (nonatomic, assign) CGFloat lineWidth;
/** 記錄valueArray當前元素的下標 */
@property (nonatomic, assign) NSInteger index;
/** 記錄當前path的中心點 */
@property (nonatomic, assign) CGPoint centerPoint;
/** 半透明Path延伸長度 */
@property (nonatomic, assign) CGFloat extendLength;
/** 記錄圓環中心 */
@property (nonatomic, assign) CGPoint pieCenter;
/** 記錄初始高度 */
@property (nonatomic, assign) CGFloat originHeight;
/** 存儲每個圓弧動畫開始的時間 */
@property (nonatomic, strong) NSMutableArray * startTimeArray;
/** 記錄每個path startAngle 和 endAngle, 數組裡存的是NSDictionary */
@property (nonatomic, strong) NSMutableArray * angelArray;
/** 標題Label */
@property (nonatomic, strong) UILabel * titleLabel;
/** 數值Label */
@property (nonatomic, strong) UILabel * valueLabel;

@end

@implementation ZFPieChart

- (NSMutableArray *)startTimeArray{
    if (!_startTimeArray) {
        _startTimeArray = [NSMutableArray array];
    }
    return _startTimeArray;
}

- (NSMutableArray *)angelArray{
    if (!_angelArray) {
        _angelArray = [NSMutableArray array];
    }
    return _angelArray;
}

/**
 *  初始化變量
 */
- (void)commonInit{
    _maxRadius = self.frame.size.width > self.frame.size.height ? self.frame.size.height : self.frame.size.width;
    _radius = _maxRadius * 0.27;
    _lineWidth = _radius;
    _totalDuration = 0.75f;
    _startAngle = ZFRadian(-90);
    _extendLength = 10.f;
    _originHeight = self.frame.size.height;
    _pieCenter = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
    _isShowDetail = YES;
    _isShowPercent = YES;
}

- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self commonInit];

        //數值Label
        self.valueLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, _radius/1.4, _radius/1.4)];
        self.valueLabel.font = [UIFont boldSystemFontOfSize:13.f];
        self.valueLabel.textAlignment = NSTextAlignmentCenter;
        self.valueLabel.textColor = [UIColor blackColor];
        self.valueLabel.numberOfLines = 0;
        self.valueLabel.center = self.pieCenter;
        [self addSubview:self.valueLabel];
    }
    return self;
}

/**
 *  添加詳情
 */
- (void)addUI{
    CGFloat valueMoney = 0.0;
    for (NSInteger i = 0; i < self.valueArray.count; i++) {
        //裝載容器
        UIView * background = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height + ADAPTATION_HEIGHT7(50) * i, self.frame.size.width, ADAPTATION_HEIGHT7(50))];
        background.tag = DetailBackgroundTag + i;
        [self addSubview:background];

        UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showTranslucencePathAction:)];
        [background addGestureRecognizer:tap];

        //線條
        UIView *lineView = [[UIView alloc] init];
        lineView.backgroundColor = [UIColor lightGrayColor];
        [background addSubview:lineView];
        [lineView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(background);
            make.left.equalTo(background).offset(10);
            make.right.equalTo(background);
            make.height.mas_offset(1);
        }];
        UIImageView *colorImage = [[UIImageView alloc] init];
        colorImage.image = IMGNAME(_nameArray[i]);
        [background addSubview:colorImage];
        [colorImage mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(background);
            make.left.equalTo(background).offset(20);
            make.size.mas_equalTo(CGSizeMake(ADAPTATION_WIDTH7(35), ADAPTATION_WIDTH7(35)));
        }];

        //名稱
        UILabel *nameLabel = [[UILabel alloc] init];
        nameLabel.text = _nameArray[i];
        nameLabel.font = [UIFont boldSystemFontOfSize:18];
        nameLabel.textAlignment = NSTextAlignmentLeft;
        [background addSubview:nameLabel];
        [nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(background);
            make.left.equalTo(colorImage.mas_right).offset(15);
            make.size.mas_equalTo(CGSizeMake(60, 30));
        }];

        //數值
        UILabel *valueLabel = [[UILabel alloc] init];
        valueLabel.font = [UIFont systemFontOfSize:16];
        valueLabel.text = [NSString stringWithFormat:@"%@元",_valueArray[i]];
        valueLabel.textAlignment = NSTextAlignmentCenter;
        [background addSubview:valueLabel];
        [valueLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerX.equalTo(background);
            make.centerY.equalTo(background);
            make.size.mas_equalTo(CGSizeMake(150, 30));
        }];
        valueMoney += [_valueArray[i] floatValue];
        self.valueLabel.text = [NSString stringWithFormat:@"總金額%.2f",valueMoney];
        //百分比
        UILabel *percentLabel = [[UILabel alloc] init];
        percentLabel.text = [self getPercent:i];
        percentLabel.font = [UIFont systemFontOfSize:16];
        percentLabel.textAlignment = NSTextAlignmentRight;
        [background addSubview:percentLabel];
        [percentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(background);
            make.right.equalTo(background).offset(-15);
            make.size.mas_equalTo(CGSizeMake(80, 30));
        }];
    }

    //重設self.frame的值
    UILabel * lastLabel = (UILabel *)[self viewWithTag:DetailBackgroundTag + self.valueArray.count - 1];
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, CGRectGetMaxY(lastLabel.frame) + 20);
}

#pragma mark - Arc(圓弧)

/**
 *  填充
 *
 *  @return UIBezierPath
 */
- (UIBezierPath *)fill{
    //需要多少度的圓弧
    CGFloat angle = [self countAngle:[_valueArray[_index] floatValue]];

    UIBezierPath * bezier = [UIBezierPath bezierPathWithArcCenter:_pieCenter radius:_radius startAngle:_startAngle endAngle:_startAngle + angle clockwise:YES];
    self.centerPoint = [self getBezierPathCenterPointWithStartAngle:_startAngle endAngle:_startAngle + angle];
    //記錄開始角度和結束角度
    NSDictionary * dict = @{@"startAngle":@(_startAngle), @"endAngle":@(_startAngle + angle)};
    [self.angelArray addObject:dict];

    _startAngle += angle;

    return bezier;
}

/**
 *  CAShapeLayer
 *
 *  @return CAShapeLayer
 */
- (CAShapeLayer *)shapeLayer{
    CAShapeLayer * layer = [CAShapeLayer layer];
    layer.fillColor = nil;
    layer.strokeColor = [_colorArray[_index] CGColor];
    layer.lineWidth = _lineWidth;
    layer.path = [self fill].CGPath;

    CABasicAnimation * animation = [self animation];
    [layer addAnimation:animation forKey:nil];

    return layer;
}

#pragma mark - 動畫

/**
 *  填充動畫過程
 *
 *  @return CABasicAnimation
 */
- (CABasicAnimation *)animation{
    CABasicAnimation * fillAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    fillAnimation.duration = [self countDuration:_index];
    fillAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    fillAnimation.fillMode = kCAFillModeForwards;
    fillAnimation.removedOnCompletion = NO;
    fillAnimation.fromValue = @(0.f);
    fillAnimation.toValue = @(1.f);

    return fillAnimation;
}

#pragma mark - 清除控件

/**
 *  清除之前所有子控件
 */
- (void)removeAllSubLayers{
    [self.angelArray removeAllObjects];
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, _originHeight);

    NSArray * subLayers = [NSArray arrayWithArray:self.layer.sublayers];
    for (CALayer * layer in subLayers) {
        if (layer != self.titleLabel.layer && layer != self.valueLabel.layer) {
            [layer removeAllAnimations];
            [layer removeFromSuperlayer];
        }
    }

    for (UIView * view in self.subviews) {
        if (view != self.titleLabel && view != self.valueLabel) {
            [view removeFromSuperview];
        }
    }
}

/**
 *  移除半透明Path
 */
- (void)removeZFTranslucencePath{
    NSMutableArray * sublayers = [NSMutableArray arrayWithArray:self.layer.sublayers];
    for (CALayer * layer in sublayers) {
        if ([layer isKindOfClass:[ZFTranslucencePath class]]) {
            [layer removeFromSuperlayer];
        }
    }
}

#pragma mark - 半透明Path

/**
 *  半透明Path
 *
 *  @param startAngle 開始角度
 *  @param endAngle   結束角度
 *  @param index      下標
 *
 *  @return ZFTranslucencePath
 */
- (ZFTranslucencePath *)translucencePathShapeLayerWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle index:(NSInteger)index{
    ZFTranslucencePath * layer = [ZFTranslucencePath layerWithArcCenter:_pieCenter radius:_radius + _extendLength startAngle:startAngle endAngle:endAngle clockwise:YES];
    layer.strokeColor = [_colorArray[index] CGColor];
    layer.lineWidth = _lineWidth + _extendLength;
    return layer;
}

#pragma mark - public method

/**
 *  重繪
 */
- (void)strokePath{
    self.userInteractionEnabled = NO;
    [self removeAllSubLayers];
    _startAngle = ZFRadian(-90);

    for (NSInteger i = 0; i < _valueArray.count; i++) {
        [self dispatch_after_withSeconds:[self.startTimeArray[i] floatValue] actions:^{
            _index = i;
            CAShapeLayer * shapeLayer = [self shapeLayer];
            [self.layer addSublayer:shapeLayer];
            _isShowPercent == YES?[self creatPercentLabel]:nil;
        }];
    }

    [self dispatch_after_withSeconds:_totalDuration actions:^{
        self.userInteractionEnabled = YES;
    }];

    _isShowDetail == YES?[self addUI]:nil;
}

#pragma mark - UIResponder

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    UITouch * touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    if (point.y > _originHeight / 8.f * 7 + 30) {
        return;
    }

    //求弧度
    CGFloat x = (point.x - _pieCenter.x);
    CGFloat y = (point.y - _pieCenter.y);
    CGFloat radian = atan2(y, x);
    //當超過180度時,要加2π
    if (y < 0 && x < 0) {
        radian = radian + ZFRadian(360);
    }

    //判斷點擊位置的角度在哪個path范圍上
    for (NSInteger i = 0; i < self.angelArray.count; i++) {
        NSDictionary * dict = self.angelArray[i];
        CGFloat startAngle = [dict[@"startAngle"] floatValue];
        CGFloat endAngle = [dict[@"endAngle"] floatValue];

        if (radian >= startAngle && radian < endAngle) {
            [self removeZFTranslucencePath];
            [self.layer addSublayer:[self translucencePathShapeLayerWithStartAngle:startAngle endAngle:endAngle index:i]];
            UILabel * percentLabel = [self viewWithTag:PercentLabelTag + i];
            [self bringSubviewToFront:percentLabel];
            self.valueLabel.text = _valueArray[i];

            return;
        }
    }
}

/**
 *  顯示半透明Path Action
 *
 *  @param sender UITapGestureRecognizer
 */
- (void)showTranslucencePathAction:(UITapGestureRecognizer *)sender{
    NSInteger index = sender.view.tag - DetailBackgroundTag;
    NSDictionary * dict = self.angelArray[index];
    CGFloat startAngle = [dict[@"startAngle"] floatValue];
    CGFloat endAngle = [dict[@"endAngle"] floatValue];

    [self removeZFTranslucencePath];
    [self.layer addSublayer:[self translucencePathShapeLayerWithStartAngle:startAngle endAngle:endAngle index:index]];
    UILabel * percentLabel = [self viewWithTag:PercentLabelTag + index];
    [self bringSubviewToFront:percentLabel];
    self.valueLabel.text = _valueArray[index];
}

#pragma mark - 獲取每個item所占百分比

/**
 *  計算每個item所占角度大小
 *
 *  @param value 每個item的value
 *
 *  @return 返回角度大小
 */
- (CGFloat)countAngle:(CGFloat)value{
    //計算百分比
    CGFloat percent = value / _totalValue;
    //需要多少度的圓弧
    CGFloat angle = M_PI * 2 * percent;
    return angle;
}

#pragma mark - 計算每個圓弧執行動畫持續時間

/**
 *  計算每個圓弧執行動畫持續時間
 *
 *  @param index 下標
 *
 *  @return CFTimeInterval
 */
- (CFTimeInterval)countDuration:(NSInteger)index{
    if (_totalDuration < 0.1f) {
        _totalDuration = 0.1f;
    }
    float count = _totalDuration / 0.1f;
    CGFloat averageAngle =  M_PI * 2 / count;
    CGFloat time = [self countAngle:[_valueArray[index] floatValue]] / averageAngle * 0.1;

    return time;
}

#pragma mark - 獲取每個path的中心點

/**
 *  獲取每個path的中心點
 *
 *  @return CGFloat
 */
- (CGPoint)getBezierPathCenterPointWithStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle{
    //一半角度(弧度)
    CGFloat halfAngle = (endAngle - startAngle) / 2;
    //中心角度(弧度)
    CGFloat centerAngle = halfAngle + startAngle;
    //中心角度(角度)
    CGFloat realAngle = ZFAngle(centerAngle);

    CGFloat center_xPos = ZFCos(realAngle) * _radius + _pieCenter.x;
    CGFloat center_yPos = ZFSin(realAngle) * _radius + _pieCenter.y;

    return CGPointMake(center_xPos, center_yPos);
}

#pragma mark - 添加百分比Label

/**
 *  添加百分比Label
 */
- (void)creatPercentLabel{
    NSString * string = [self getPercent:_index];
    CGRect rect = [string stringWidthRectWithSize:CGSizeMake(0, 0) fontOfSize:9.f];

    UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, rect.size.width, rect.size.height)];
    if ([string isEqualToString:@"0.00%"]) {
        label.text = @"";
    }else {
        label.text = string;
    }
    label.alpha = 0.f;
    label.textAlignment = NSTextAlignmentCenter;
    label.font = [UIFont boldSystemFontOfSize:9.f];
    label.center = self.centerPoint;
    label.tag = PercentLabelTag + _index;
    [self addSubview:label];

    [UIView animateWithDuration:[self countDuration:_index] animations:^{
        label.alpha = 1.f;
    }];

    //獲取r,g,b三色值
    CGFloat red = [_colorArray[_index] red];
    CGFloat green = [_colorArray[_index] green];
    //path顏色為深色時,更改文字顏色
    if ((red < 180.f && green < 180.f)) {
        label.textColor = [UIColor whiteColor];
    }
}

/**
 *  計算百分比
 *
 *  @return NSString
 */
- (NSString *)getPercent:(NSInteger)index{
    CGFloat percent = [_valueArray[index] floatValue] / _totalValue * 100;
    NSString * string;
    if (self.percentType == kPercentTypeDecimal) {
        string = [NSString stringWithFormat:@"%.2f%%",percent];
    }else if (self.percentType == kPercentTypeInteger){
        string = [NSString stringWithFormat:@"%d%%",(int)roundf(percent)];
    }
    return string;
}

#pragma mark - 重寫setter,getter方法

- (void)setValueArray:(NSMutableArray *)valueArray{
    _valueArray = valueArray;
    _totalValue = 0;
    [self.startTimeArray removeAllObjects];
    CFTimeInterval startTime = 0.f;
    //計算總數
    for (NSInteger i = 0; i < valueArray.count; i++) {
        _totalValue += [valueArray[i] floatValue];
    }

    //計算每個path的開始時間
    for (NSInteger i = 0; i < valueArray.count; i++) {
        [self.startTimeArray addObject:[NSNumber numberWithDouble:startTime]];
        CFTimeInterval duration = [self countDuration:i];
        startTime += duration;
    }
}

@end

餅狀圖效果

#import “ViewController.h”

**#import "ViewController.h"**
#import 
@interface ViewController : UIViewController

@end

**#import "ViewController.m"**

#import "ViewController.h"
#import "ZFChart.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    ZFPieChart *pieChart = [[ZFPieChart alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_WIDTH)];
    pieChart.valueArray = [NSMutableArray arrayWithArray:@"410", @"510", @"380", @"420", @"260",nil];
pieChart.nameArray = [NSMutableArray arrayWithObjects:@"購物", @"美食", @"住房", @"交通", @"娛樂", nil];
pieChart.colorArray = [NSMutableArray arrayWithObjects:ZFColor(253, 118, 152, 1), ZFColor(254, 223, 219, 1), ZFColor(254, 206, 103, 1), ZFColor(81, 146, 218, 1), ZFColor(112, 182, 146, 1), nil];
[self.view addSubview:pieChart];
[self.pieChart strokePath];

}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

效果圖

這裡寫圖片描述
這裡寫圖片描述

餅狀圖效果圖。本文的Demo是借鑒自網上,非博主純原創。敬請諒解。
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved