前言
- 最近项目中要求使用柱状图来显示数据,但是要求在柱子上显示不同的颜色,查找了很多第三方的库,然而并没有找到合适的,无奈之下只好自己进行封装.
- 参考资料
http://blog.csdn.net/nb_killer/article/details/51023948
http://www.cnblogs.com/nightcat/p/ios_01.html
PNChart 库
效果图
- 柱子的高度是到顶部的,由于柱子的颜色和View背景色一致了,无法看清,更改下背景色就能看到了,柱子的最大值是1440,可以根据自己需求进行更改 这个属性 MAX_TIME
本文主要参考了PNChart ,有兴趣的同学可以去学习下
废话不说了,直接上代码主要分为3个类
MKBar: 是单个柱子,包括绘制和数据的分段处理
BarLayerView : 主要是绘制多个柱子,对柱子进行更新等
ViewController : 展示界面
MKBar
MKBar.h
#import
@interface MKBar : UIView
@property (nonatomic,copy)NSString *titleStr;//标题
@property (nonatomic,strong)NSMutableArray *dataArr;//数据 注意数据格式
@end
MKBar.m
#define MAX_TIME 1440
#define RGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
@interface MKBar ()
@property (nonatomic) CATextLayer* textLayer;//标题Layer
@property (nonatomic,strong)NSMutableArray *barArr;//柱子上面进度数据
@property (nonatomic,assign)float totalNum;//总的进度时间
@property (nonatomic,strong)UILabel *titleLab;//下面标题 也可以使用CATextLayer
@end
@implementation MKBar
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
}
return self;
}
-(void)setTitleStr:(NSString *)titleStr
{
_titleStr = titleStr;
[self addSubview:self.titleLab];
//CABasicAnimation *fade = [self fadeAnimation];
//[self.textLayer addAnimation:fade forKey:nil];
//[self.layer addSublayer:self.textLayer];
}
-(void)setDataArr:(NSMutableArray *)dataArr
{
_dataArr = dataArr;
self.barArr = [self barProgressArr:_dataArr];
[self setProgress];
}
#pragma mark ---画图
-(void)setProgress
{
__block float a = 0;
//遍历数组
[self.barArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//画路径
UIBezierPath *beziPath = [UIBezierPath bezierPath];
beziPath.lineWidth = 0.0;//线的宽度
//起点坐标
[beziPath moveToPoint:CGPointMake(15,self.bounds.size.height-20)];
//终点坐标
[beziPath addLineToPoint:CGPointMake(15,(MAX_TIME-self.totalNum)/MAX_TIME*(self.bounds.size.height-20))];
beziPath.lineCapStyle = kCGLineCapRound;
beziPath.lineJoinStyle = kCGLineJoinRound;
[beziPath stroke];
//画图
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.strokeColor = [obj[@"strokeColor"]CGColor];
shapeLayer.lineWidth = 30.0;//宽度 目前是固定宽度 可以根据情况进行修改
shapeLayer.strokeStart = a;//起始点
shapeLayer.strokeEnd = [obj[@"precent"] floatValue]+a;//结束点
a = shapeLayer.strokeEnd;//从上一个起始点开始画图
shapeLayer.path = beziPath.CGPath;//产生联系
[self.layer addSublayer:shapeLayer];
//动画
CABasicAnimation*pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration=1.0f;
pathAnimation.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[email protected];
pathAnimation.toValue=@(1);
[shapeLayer addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
}];
}
#pragma mark ---处理进度数据
-(NSMutableArray *)barProgressArr:(NSMutableArray *)dataArr
{
NSMutableArray *barProgArr = [[NSMutableArray alloc]initWithCapacity:0];
self.totalNum = 0.0;//总的时间
float value = 0.0;//每一段时间
NSString *boolStr;
//计算总时间
for (NSDictionary *dic in dataArr)
{
value = [dic[@"precent"] floatValue];
self.totalNum = self.totalNum + value;
}
//计算进度值
for (NSDictionary *dic in dataArr)
{
value = [dic[@"precent"] floatValue];
boolStr = dic[@"strokeColor"];
NSMutableDictionary *progDic = [[NSMutableDictionary alloc]initWithCapacity:0];
//根据BOOL确定颜色 当然也可以添加多种颜色
if ([boolStr isEqualToString:@"1"])
{
[progDic setObject:[UIColor redColor] forKey:@"strokeColor"];
}
else
{
[progDic setObject:RGB(83, 193, 124) forKey:@"strokeColor"];
}
//计算进度 添加进数组
[progDic setObject:@(value/self.totalNum) forKey:@"precent"];
[barProgArr addObject:progDic];
}
return barProgArr;
}
-(UILabel *)titleLab
{
if (!_titleLab)
{
_titleLab = [[UILabel alloc]initWithFrame:CGRectMake(0, self.bounds.size.height-20, self.bounds.size.width, 20)];
_titleLab.font = [UIFont systemFontOfSize:14.0];
_titleLab.textAlignment = NSTextAlignmentCenter;
_titleLab.textColor = [UIColor whiteColor];
_titleLab.text = self.titleStr;
}
return _titleLab;
}
#pragma mark ---可以使用CATextLayer
-(CATextLayer*)textLayer
{
if (!_textLayer) {
_textLayer = [[CATextLayer alloc]init];
_textLayer.string = self.titleStr;
_textLayer.frame = CGRectMake(0, self.bounds.size.height-20, self.bounds.size.width, 20);
[_textLayer setAlignmentMode:kCAAlignmentCenter];
[_textLayer setForegroundColor:[[UIColor whiteColor] CGColor]];
_textLayer.fontSize = 14.0;
}
return _textLayer;
}
//动画
-(CABasicAnimation*)fadeAnimation
{
CABasicAnimation* fadeAnimation = nil;
fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeAnimation.fromValue = [NSNumber numberWithFloat:0.0];
fadeAnimation.toValue = [NSNumber numberWithFloat:1.0];
fadeAnimation.duration = 2.0;
return fadeAnimation;
}
BarLayerView
BarLayerView.h
#import
@interface BarLayerView : UIView
@property (nonatomic,strong)NSMutableArray *xArr;//X轴数据
@property (nonatomic,strong)NSMutableArray *dataArr;//进度数据
@property (nonatomic,strong)NSMutableArray *barArr;//存放柱子的数组 用来删除
-(void)strokeMKBarChart;//绘制
@end
BarLayerView.m
#import "BarLayerView.h"
#import "MKBar.h"
#define RGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
@implementation BarLayerView
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
self.barArr = [[NSMutableArray alloc]initWithCapacity:0];
}
return self;
}
-(void)setXArr:(NSMutableArray *)xArr
{
_xArr = xArr;
}
-(void)setDataArr:(NSMutableArray *)dataArr
{
_dataArr = dataArr;
}
-(void)strokeMKBarChart
{
//删除所有的柱子
[self viewCleanupForCollection:self.barArr];
[self upDateMKBarChart];
}
//绘图
-(void)upDateMKBarChart
{
CGFloat barInterval = (self.bounds.size.width-(30*(self.xArr.count+1)))/(self.xArr.count-1);
for (int a = 0; a < self.xArr.count; a++)
{
MKBar *bar = [[MKBar alloc]initWithFrame:CGRectMake(10+(barInterval+30)*a, 0, 30, self.bounds.size.height)];
bar.backgroundColor = RGB(54, 63, 86);
[bar setDataArr:self.dataArr[a]];
[bar setTitleStr:self.xArr[a]];
[self.barArr addObject:bar];//添加进数组中,重绘时删除,重新创建
[self addSubview:bar];
}
}
//删除所有的柱子
- (void)viewCleanupForCollection:(NSMutableArray *)array
{
if (array.count) {
[array makeObjectsPerformSelector:@selector(removeFromSuperview)];
[array removeAllObjects];
}
}
ViewController
#import "ViewController.h"
#import "BarLayerView.h"
#import "MKBar.h"
#define RGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
@interface ViewController ()
@property (nonatomic,strong)CAShapeLayer *shapeLayer;
@property (nonatomic,strong)BarLayerView *barLayerView;
@end
- (void)viewDidLoad {
[super viewDidLoad];
//测试数据
//单个柱子上的分段数据
NSMutableArray *arr = [[NSMutableArray alloc]initWithCapacity:0];
//需要展示几段
[arr addObject:@{@"precent":@"200",@"strokeColor":@"1"}];
[arr addObject:@{@"precent":@"100",@"strokeColor":@"0"}];
[arr addObject:@{@"precent":@"200",@"strokeColor":@"1"}];
[arr addObject:@{@"precent":@"300",@"strokeColor":@"0"}];
[arr addObject:@{@"precent":@"200",@"strokeColor":@"1"}];
//柱子个数
NSMutableArray *dataArr = [[NSMutableArray alloc]initWithCapacity:0];
[dataArr addObject:arr];
[dataArr addObject:arr];
[dataArr addObject:arr];
[dataArr addObject:arr];
[dataArr addObject:arr];
[dataArr addObject:arr];
[dataArr addObject:arr];
//X轴数据
NSMutableArray *xArr = [[NSMutableArray alloc]initWithCapacity:0];
[xArr addObject:@"1"];
[xArr addObject:@"2"];
[xArr addObject:@"3"];
[xArr addObject:@"4"];
[xArr addObject:@"5"];
[xArr addObject:@"6"];
[xArr addObject:@"7"];
self.barLayerView = [[BarLayerView alloc]initWithFrame:CGRectMake(00, 100, self.view.bounds.size.width, 200)];
self.barLayerView.backgroundColor = RGB(54, 63, 86);
[self.barLayerView setDataArr:dataArr];//设置柱子进度
[self.barLayerView setXArr:xArr];//设置XLable
[self.barLayerView strokeMKBarChart];//重绘
[self.view addSubview:self.barLayerView];
}
当然Demo也有许多需要更改的地方,比如固定的宽度等等
如果感觉对您有帮助,请顺手点个赞,哈哈....
原创文章,如果转载,请注明出处,谢谢.