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是借鉴自网上,非博主纯原创。敬请谅解。