前言
- 最近項目中要求使用柱狀圖來顯示數據,但是要求在柱子上顯示不同的顏色,查找了很多第三方的庫,然而并沒有找到合適的,無奈之下只好自己進行封裝.
- 參考資料
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 <UIKit/UIKit.h>
@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];
pathAnimation.fromValue=@0.0f;
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 <UIKit/UIKit.h>
@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也有許多需要更改的地方,比如固定的寬度等等
如果感覺對您有幫助,請順手點個贊,哈哈....
原創文章,如果轉載,請注明出處,謝謝.