
現(xiàn)在很多app中的數(shù)據(jù)統(tǒng)計(jì)功能都會(huì)使用到
柱狀圖,折線圖等來進(jìn)行數(shù)據(jù)的展示,可能有一些比較牛的大神會(huì)選擇自己繪制,至于我嘛,還是老老實(shí)實(shí)的用網(wǎng)上開源的工具吧,先把我寫的Demo給大家放在這里,可以對(duì)照著下面的講解看。
在做這個(gè)功能之前我上網(wǎng)查了一些別人的實(shí)現(xiàn)方式,一種是使用開源組件ios-charts,這個(gè)是使用swift開發(fā)的組件,可以直接在iOS項(xiàng)目中進(jìn)行集成使用,我用這個(gè)也實(shí)現(xiàn)了功能所需的效果,但是我總感覺這個(gè)東西不好封裝,有興趣的可以去試試。
另一種是使用百度的開源圖表工具ECharts,不過不太幸運(yùn)的是這個(gè)組件是使用JS來寫的,有JS功底的呢就可以直接來使用。針對(duì)這個(gè)問題有一位活雷鋒出現(xiàn)了,Pluto-Y對(duì)ECharts進(jìn)行了封裝,名字叫做iOS-Echarts,也就是我實(shí)現(xiàn)功能所使用的組件。
雖然這位活雷鋒為我們鋪好了前期的道路,但是這個(gè)組件沒有注釋,這個(gè)問題就相當(dāng)嚴(yán)重了,給大家簡單的看一下Pluto-Y的demo中柱狀圖效果。

再給大家看一下這個(gè)簡單的柱狀圖的實(shí)現(xiàn)代碼
+ (PYOption *)basicBarOption {
return [PYOption initPYOptionWithBlock:^(PYOption *option) {
option.titleEqual([PYTitle initPYTitleWithBlock:^(PYTitle *title) {
title.textEqual(@"世界人口總量")
.subtextEqual(@"數(shù)據(jù)來自網(wǎng)絡(luò)");
}])
.gridEqual([PYGrid initPYGridWithBlock:^(PYGrid *grid) {
grid.xEqual(@40).x2Equal(@50);
}])
.tooltipEqual([PYTooltip initPYTooltipWithBlock:^(PYTooltip *tooltip) {
tooltip.triggerEqual(PYTooltipTriggerAxis);
}])
.legendEqual([PYLegend initPYLegendWithBlock:^(PYLegend *legend) {
legend.dataEqual(@[@"2011年", @"2012年"]);
}])
.toolboxEqual([PYToolbox initPYToolboxWithBlock:^(PYToolbox *toolbox) {
toolbox.showEqual(YES)
.featureEqual([PYToolboxFeature initPYToolboxFeatureWithBlock:^(PYToolboxFeature *feature) {
feature.markEqual([PYToolboxFeatureMark initPYToolboxFeatureMarkWithBlock:^(PYToolboxFeatureMark *mark) {
mark.showEqual(YES);
}])
.dataViewEqual([PYToolboxFeatureDataView initPYToolboxFeatureDataViewWithBlock:^(PYToolboxFeatureDataView *dataView) {
dataView.showEqual(YES).readOnlyEqual(NO);
}])
.magicTypeEqual([PYToolboxFeatureMagicType initPYToolboxFeatureMagicTypeWithBlock:^(PYToolboxFeatureMagicType *magicType) {
magicType.showEqual(YES).typeEqual(@[PYSeriesTypeLine, PYSeriesTypeBar]);
}])
.restoreEqual([PYToolboxFeatureRestore initPYToolboxFeatureRestoreWithBlock:^(PYToolboxFeatureRestore *restore) {
restore.showEqual(YES);
}]);
}]);
}])
.calculableEqual(YES)
.addXAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
axis.typeEqual(PYAxisTypeValue)
.boundaryGapEqual(@[@0, @0.01]);
}])
.addYAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
axis.typeEqual(PYAxisTypeCategory)
.addDataArr(@[@"巴西",@"印尼",@"美國",@"印度",@"中國",@"世界人口(萬)"]);
}])
.addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
series.nameEqual(@"2011年")
.typeEqual(PYSeriesTypeBar)
.addDataArr(@[@18203, @23489, @29034, @104970, @131744, @630230]);
}])
.addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
series.nameEqual(@"2012年")
.typeEqual(PYSeriesTypeBar)
.addDataArr(@[@19325, @23438, @31000, @121594, @134141, @681807]);
}]);
}];
}
我第一次看簡直毫無頭緒,再歷經(jīng)了兩天的不斷嘗試以及查詢百度的JS文檔,總算是稍稍的理解了其中的一部分實(shí)現(xiàn)方式。

言歸正傳,先給大家看一下我所實(shí)現(xiàn)的界面效果圖。

這是一個(gè)最為常規(guī)的條形圖,也叫柱狀圖,我們先簡單的看一下它的實(shí)現(xiàn)代碼。
#import "SimpleBarChartViewController.h"
//引入開源庫的頭文件
#import <iOS_Echarts/iOS-Echarts.h>
//這是我自己封裝后寫的一個(gè)類
#import "ZRChartsHelper.h"
@interface SimpleBarChartViewController ()
//定義一個(gè)PYEchartsView,這個(gè)是圖表繪制的view
@property (nonatomic, strong)PYEchartsView *zrSimpleChartsView;
@end
接著我們?yōu)檫@個(gè)view進(jìn)行相應(yīng)的布局
//布局chartsView
- (void)chartsViewLayout{
self.zrSimpleChartsView = [[PYEchartsView alloc] initWithFrame:CGRectMake(0, getRectNavAndStatusHight, [UIScreen mainScreen].bounds.size.width, 350)];
self.zrSimpleChartsView.backgroundColor = [UIColor grayColor];
[self.view addSubview:self.zrSimpleChartsView];
NSArray *chart1Array = @[@"56",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89"];
NSArray *titleArray = @[@"人員1",@"人員2",@"人員3",@"人員4",@"人員5",@"人員6",@"人員7",@"人員8",@"人員9",@"人員10",@"人員11"];
//為內(nèi)容進(jìn)行渲染
ZRChartsHelper *helper = [[ZRChartsHelper alloc] init];
[helper setZRSimpleBarChartView:self.zrSimpleChartsView barValues:chart1Array xValues:titleArray];
}
繪制的主要代碼我都寫到了ZRChartsHelper這個(gè)類中,我們再看一下這個(gè)最基礎(chǔ)簡單的條形圖的實(shí)現(xiàn)代碼。
- (void)setZRSimpleBarChartView:(PYEchartsView *)chartView barValues:(NSArray *)barValues xValues:(NSArray *)xvals{
//初始化一個(gè)Option,對(duì)其屬性進(jìn)行設(shè)置,來達(dá)到我們想要的效果
PYOption *option = [PYOption initPYOptionWithBlock:^(PYOption *option) {
option.tooltipEqual([PYTooltip initPYTooltipWithBlock:^(PYTooltip *tooltip) {
tooltip.triggerEqual(PYTooltipTriggerAxis)
.axisPointerEqual([PYAxisPointer initPYAxisPointerWithBlock:^(PYAxisPointer *axisPoint) {
axisPoint.typeEqual(PYAxisPointerTypeShadow);
}]);
}])
//這個(gè)屬性是對(duì)圖表下方的文字控件進(jìn)行設(shè)置
.legendEqual([PYLegend initPYLegendWithBlock:^(PYLegend *legend) {
//文字的內(nèi)容
legend.dataEqual(@[@"新增事件"]);
//文字控件的縱坐標(biāo)
legend.yEqual(@300);
}])
//這個(gè)屬性是對(duì)整個(gè)圖表的位置進(jìn)行設(shè)置
.gridEqual([PYGrid initPYGridWithBlock:^(PYGrid *grid) {
//第一個(gè)40為X軸距離左邊的距離,第二個(gè)x2為X軸末端距離view右面邊界的距離
grid.xEqual(@40).x2Equal(@50);
//圖表距離頂部的距離
grid.yEqual(@10);
//圖表的高度設(shè)置
grid.heightEqual(@250);
}])
//這個(gè)屬性是設(shè)置圖表可左右滑動(dòng),很多情況下可能X軸要展示很多數(shù)據(jù),因此會(huì)產(chǎn)生堆積,加了這個(gè)便可以左右滑動(dòng)條形圖來查看數(shù)據(jù)
.dataZoomEqual([PYDataZoom initPYDataZoomWithBlock:^(PYDataZoom *dataZoom) {
dataZoom.yEqual(@335);
dataZoom.heightEqual(@10);
//設(shè)置為顯示滾動(dòng)欄
dataZoom.showEqual(YES)
//下面這兩個(gè)屬性是設(shè)置界面一開始展示那一部分的內(nèi)容,這里為圖表30%~70%間的內(nèi)容
.startEqual(@30)
.endEqual(@70);
}])
//設(shè)置工具欄,這個(gè)我沒有讓它進(jìn)行顯示,因此show這個(gè)屬性我設(shè)置為隱藏,大家可以去看看有很多功能
.toolboxEqual([PYToolbox initPYToolboxWithBlock:^(PYToolbox *toolbox) {
//設(shè)置為隱藏
toolbox.showEqual(NO)
.orientEqual(PYOrientVertical)
.xEqual(PYPositionRight)
.yEqual(PYPositionCenter)
.featureEqual([PYToolboxFeature initPYToolboxFeatureWithBlock:^(PYToolboxFeature *feature) {
feature.markEqual([PYToolboxFeatureMark initPYToolboxFeatureMarkWithBlock:^(PYToolboxFeatureMark *mark) {
mark.showEqual(YES);
}])
.dataViewEqual([PYToolboxFeatureDataView initPYToolboxFeatureDataViewWithBlock:^(PYToolboxFeatureDataView *dataView) {
dataView.showEqual(YES).readOnlyEqual(NO);
}])
.magicTypeEqual([PYToolboxFeatureMagicType initPYToolboxFeatureMagicTypeWithBlock:^(PYToolboxFeatureMagicType *magicType) {
magicType.showEqual(YES).typeEqual(@[PYSeriesTypeLine, PYSeriesTypeBar, @"stack", @"tiled"]);
}])
.restoreEqual([PYToolboxFeatureRestore initPYToolboxFeatureRestoreWithBlock:^(PYToolboxFeatureRestore *restore) {
restore.showEqual(YES);
}]);
}]);
}])
.calculableEqual(NO)
//設(shè)置X軸title,有多少個(gè)就在數(shù)組中寫入多少個(gè)
.addXAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
axis.typeEqual(PYAxisTypeCategory)
//這里在我封裝過后本應(yīng)寫為xvals,方便大家理解我直接填寫了數(shù)組進(jìn)去
.addDataArr(@[@"人員1",@"人員2",@"人員3",@"人員4",@"人員5",@"人員6",@"人員7",@"人員8",@"人員9",@"人員10",@"人員11"]);
}])
//設(shè)置Y軸title,一般默認(rèn)是數(shù)字
.addYAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
//Y軸顯示的值類型,這里為直接顯示數(shù)據(jù)值
axis.typeEqual(PYAxisTypeValue);
//Y軸的位置,這里是在左邊
axis.positionEqual(PYPositionLeft);
}])
//這里設(shè)置柱子的屬性
.addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
//這個(gè)值可以隨意起名稱,他不會(huì)顯示在界面中,但是這個(gè)值很重要,我會(huì)在接下來復(fù)雜的柱狀圖中說明
series.stackEqual(@"事件類型")
//柱子的名稱,與上方我們設(shè)置過的表格下方的控件相對(duì)應(yīng)
.nameEqual(@"新增事件")
//類型,bar為柱狀圖,如果設(shè)置為line則顯示為折線
.typeEqual(PYSeriesTypeBar)
//設(shè)置柱子的樣式
.itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
//是否顯示柱子的數(shù)值,以及顯示的位置
label.showEqual(YES).positionEqual(@"inside");
}]);
}]);
}])
//設(shè)置柱子的數(shù)值,X軸有多少個(gè)單位,這個(gè)數(shù)組就要對(duì)應(yīng)有多少值,封裝后這里應(yīng)填寫barValues
.dataEqual(@[@"56",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89"]);
}]);
}];
//為負(fù)責(zé)渲染的view設(shè)置渲染option
[chartView setOption:option];
//加載圖表渲染
[chartView loadEcharts];
}
以上就是一個(gè)最簡單的條形圖的設(shè)置,其實(shí)還好不算復(fù)雜,但是產(chǎn)品經(jīng)理怎么會(huì)這么輕松的放過你。

接下來就給大家看一下我司產(chǎn)品經(jīng)理的需求實(shí)現(xiàn)圖。

怎么樣,這個(gè)的設(shè)置就有點(diǎn)復(fù)雜了,其實(shí)說復(fù)雜也沒有很復(fù)雜,掌握規(guī)律就好了,我們再來看一下這個(gè)的實(shí)現(xiàn)代碼。
//布局chartsView
- (void)chartsViewLayout{
self.zrchartsView = [[PYEchartsView alloc] initWithFrame:CGRectMake(0, getRectNavAndStatusHight, [UIScreen mainScreen].bounds.size.width, 350)];
self.zrchartsView.backgroundColor = [UIColor grayColor];
[self.view addSubview:self.zrchartsView];
//這個(gè)數(shù)組的結(jié)構(gòu)是數(shù)組中嵌套數(shù)組,大家可以使用別的數(shù)據(jù)格式來進(jìn)行封裝
NSArray *chart1Array = @[
@[@"56",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89",@"36",@"89"],
@[@"34",@"46",@"26",@"46",@"26",@"46",@"26",@"46",@"26",@"46",@"26"],
@[@"37",@"25",@"24",@"25",@"24",@"25",@"24",@"25",@"24",@"25",@"24"],
@[@"98",@"56",@"35",@"56",@"35",@"56",@"35",@"56",@"35",@"56",@"35"]
];
//X軸的數(shù)據(jù)
NSArray *titleArray = @[@"人員1",@"人員2",@"人員3",@"人員4",@"人員5",@"人員6",@"人員7",@"人員8",@"人員9",@"人員10",@"人員11"];
//為內(nèi)容進(jìn)行渲染
ZRChartsHelper *helper = [[ZRChartsHelper alloc] init];
[helper setZRStackBarChartView:self.zrchartsView barValues:chart1Array xValues:titleArray];
}
開始還是一樣的,我們先布局,然后使用helper來進(jìn)行界面的渲染,再來看一下stackbar的實(shí)現(xiàn)代碼。
- (void)setZRStackBarChartView:(PYZoomEchartsView *)chartView barValues:(NSArray *)barValues xValues:(NSArray *)xvals{
PYOption *option = [PYOption initPYOptionWithBlock:^(PYOption *option) {
option.tooltipEqual([PYTooltip initPYTooltipWithBlock:^(PYTooltip *tooltip) {
tooltip.triggerEqual(PYTooltipTriggerAxis)
.axisPointerEqual([PYAxisPointer initPYAxisPointerWithBlock:^(PYAxisPointer *axisPoint) {
axisPoint.typeEqual(PYAxisPointerTypeShadow);
}]);
}])
.legendEqual([PYLegend initPYLegendWithBlock:^(PYLegend *legend) {
legend.dataEqual(@[@"已處理",@"待銷項(xiàng)",@"已銷項(xiàng)",@"新增事件"]);
legend.yEqual(@300);
}])
.gridEqual([PYGrid initPYGridWithBlock:^(PYGrid *grid) {
grid.xEqual(@40).x2Equal(@50);
grid.yEqual(@10);
grid.heightEqual(@250);
}])
.dataZoomEqual([PYDataZoom initPYDataZoomWithBlock:^(PYDataZoom *dataZoom) {
dataZoom.yEqual(@335);
dataZoom.heightEqual(@10);
dataZoom.showEqual(YES)
.startEqual(@30)
.endEqual(@70);
}])
.toolboxEqual([PYToolbox initPYToolboxWithBlock:^(PYToolbox *toolbox) {
toolbox.showEqual(NO)
.orientEqual(PYOrientVertical)
.xEqual(PYPositionRight)
.yEqual(PYPositionCenter)
.featureEqual([PYToolboxFeature initPYToolboxFeatureWithBlock:^(PYToolboxFeature *feature) {
feature.markEqual([PYToolboxFeatureMark initPYToolboxFeatureMarkWithBlock:^(PYToolboxFeatureMark *mark) {
mark.showEqual(YES);
}])
.dataViewEqual([PYToolboxFeatureDataView initPYToolboxFeatureDataViewWithBlock:^(PYToolboxFeatureDataView *dataView) {
dataView.showEqual(YES).readOnlyEqual(NO);
}])
.magicTypeEqual([PYToolboxFeatureMagicType initPYToolboxFeatureMagicTypeWithBlock:^(PYToolboxFeatureMagicType *magicType) {
magicType.showEqual(YES).typeEqual(@[PYSeriesTypeLine, PYSeriesTypeBar, @"stack", @"tiled"]);
}])
.restoreEqual([PYToolboxFeatureRestore initPYToolboxFeatureRestoreWithBlock:^(PYToolboxFeatureRestore *restore) {
restore.showEqual(YES);
}]);
}]);
}])
.calculableEqual(NO)
//設(shè)置X軸title,有多少個(gè)就在數(shù)組中寫入多少個(gè)
.addXAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
axis.typeEqual(PYAxisTypeCategory)
.addDataArr(xvals);
}])
//設(shè)置Y軸title,一般默認(rèn)是數(shù)字
.addYAxis([PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
axis.typeEqual(PYAxisTypeValue);
axis.positionEqual(PYPositionLeft);
}])
//這個(gè)地方設(shè)置X軸每個(gè)單位中有幾個(gè)柱狀圖,每個(gè)柱狀圖有幾層
//******這里的設(shè)置就是重點(diǎn)******//
//大家可以看到,下面進(jìn)行了四項(xiàng)設(shè)置,他們的nameEqual這個(gè)屬性名稱都不一樣,但是stackEqual這個(gè)屬性的內(nèi)容都一樣,這樣就會(huì)實(shí)現(xiàn)我們所要的堆積效果
.addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
series.stackEqual(@"事件類型")
.nameEqual(@"已處理")
.typeEqual(PYSeriesTypeBar)
.itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
label.showEqual(YES).positionEqual(@"inside");
}]);
}]);
}])
.dataEqual(barValues[0]);
}])
.addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
series.stackEqual(@"事件類型")
.nameEqual(@"待銷項(xiàng)")
.typeEqual(PYSeriesTypeBar)
.itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
label.showEqual(YES).positionEqual(@"inside");
}]);
}]);
}])
.dataEqual(barValues[1]);
}])
.addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
series.stackEqual(@"事件類型")
.nameEqual(@"已銷項(xiàng)")
.typeEqual(PYSeriesTypeBar)
.itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
normal.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
label.showEqual(YES).positionEqual(@"inside");
}]);
}]);
}])
.dataEqual(barValues[2]);
}])
.addSeries([PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
series.stackEqual(@"事件類型")
.nameEqual(@"新增事件")
.typeEqual(PYSeriesTypeBar)
.dataEqual(barValues[3]);
}]);
}];
[chartView setOption:option];
[chartView loadEcharts];
}
可以看到實(shí)現(xiàn)柱狀圖的效果的關(guān)鍵就是stackEqual,nameEqual這兩個(gè)屬性,大家可以嘗試一下,設(shè)置幾個(gè)不同的stackEqual,柱狀圖就會(huì)呈現(xiàn)一個(gè)X軸對(duì)應(yīng)多個(gè)柱子的效果,具體的效果以及代碼我都寫在Demo中了,Demo會(huì)在文章最下面的地址中給大家下載。
其實(shí)以上兩個(gè)界面的實(shí)現(xiàn)ios-charts這個(gè)組件也可以輕松的做到,我覺得不太方便的地方就是,這個(gè)組件面對(duì)混合圖表的設(shè)置看起來有那么一絲絲不太友好,導(dǎo)致我回去鉆研了兩天ECharts。

這種條形圖加折線圖的混合顯示圖表還是花了我一點(diǎn)時(shí)間去看文檔
的,先去看了一下JS代碼中如何設(shè)置雙Y軸,再回到iOS的項(xiàng)目中試試能不能找到設(shè)置雙Y軸的JS同名屬性,如何設(shè)置坐標(biāo)的顯示格式等等,所以推薦大家遇到自己不太知道的實(shí)現(xiàn)方式時(shí),去看看百度文檔中的JS代碼的設(shè)置,再去ECharts中尋找同名屬性去試試,我也是慢慢試出來的。
關(guān)鍵實(shí)現(xiàn)代碼:
//Y軸的設(shè)置變成一個(gè)數(shù)組,裝入了兩個(gè)Y軸
.addYAxisArr(@[[PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
axis.typeEqual(PYAxisTypeValue);
//位置靠左
axis.positionEqual(PYPositionLeft);
}],[PYAxis initPYAxisWithBlock:^(PYAxis *axis) {
axis.typeEqual(PYAxisTypeValue);
//位置靠右
axis.positionEqual(PYPositionRight);
//顯示格式為百分比
axis.axisLabel.formatterEqual(@"{value} %");
}]])
[PYCartesianSeries initPYCartesianSeriesWithBlock:^(PYCartesianSeries *series) {
series.stackEqual(@"事件類型");
series.nameEqual(@"銷項(xiàng)率");
series.yAxisIndexEqual(@(1))
//設(shè)置類型為Line(折線)
.typeEqual(PYSeriesTypeLine)
.dataEqual(lineValues)
.itemStyleEqual([PYItemStyle initPYItemStyleWithBlock:^(PYItemStyle *itemStyle) {
itemStyle.normalEqual([PYItemStyleProp initPYItemStylePropWithBlock:^(PYItemStyleProp *normal) {
normal.borderColorEqual([PYColor colorWithHexString:@"#fff"])
.borderWidthEqual(@2)
//設(shè)置折線上label顯示的內(nèi)容
.labelEqual([PYLabel initPYLabelWithBlock:^(PYLabel *label) {
// 折線內(nèi)容顯示位置
label.positionEqual(@"inside")
//顯示為百分比
.formatterEqual(@"{c}%")
//文字顏色
.textStyleEqual([PYTextStyle initPYTextStyleWithBlock:^(PYTextStyle *textStyle) {
textStyle.colorEqual([PYColor colorWithHexString:@"#fff"]);
}]);
}]);
}]);
}]);
}]]);
以上就是幾種柱狀圖的實(shí)現(xiàn)方式,應(yīng)該夠大部分場景使用了,我的demo中還封裝了簡單的餅狀圖和環(huán)狀圖,有新的圖表效果封裝我會(huì)持續(xù)更新demo,大家對(duì)照我的博客和demo理解了之后完全可以針對(duì)自己的項(xiàng)目做更好的封裝,我這個(gè)為了趕工可能有點(diǎn)粗糙,如果有幫到你就幫我點(diǎn)個(gè)贊就好啦。

Demo地址:ZRChartsHelper