前言
最近OC項目中使用到了charts做圖標繪制,確實是一個很酷并且功能強大的類庫。里面包含了各式各樣的圖標樣式,但是使用的是Swift語言編寫,所以就涉及到混編的一些操作配置。
你可以通過兩種方式集成進你的項目中:
- 下載后手動添加 (本文主講)
- Cocopods的方式集成
注意一下使用條件:值得注意的是工程的 Tagerts 最低設置 8.0
解壓后的文件夾里面的內容是這個樣子的,如下圖:
導入工程中的步驟
-
新建工程
新建工程,取名為ImportChartsDemo.
-
復制Charts整個文件到ImportChartsDemo工程中
就是把上圖中解壓后的文件(剔除紅色框中的文件,當然也可以剔除其他一些沒有用的文件,由于我沒有剔除多余的文件,并最終集成成功,所以就暫時視除了紅框內的文件都需要)拷貝到ImportChartsDemo主工程文件夾下。
-
導入Charts.xcodeproj
右擊項目,選擇 -> Add Files to”xx”, 在彈出的選擇文件框中選擇”Charts.xcodeproj”(注意:不要選擇文件夾)。
添加Charts.framework
找到General->Embedded Binaries,點擊+號添加Charts.framework,如下圖:
添加的iOS的framework,如下圖:
-
建立OC和Swift的橋接文件
在ImportChartsDemo工程中新建一個Swift文件,名字隨便取,這時候會提示是否建立橋接文件,直接選Create Bridging Header 選項,如下圖:
建立橋接文件
新建完成后,會自動生成一個橋接文件,如下圖:
-
設置編譯選項及引入Charts
1.設置編譯選項
找到Build Settings -> Embedded Content Contains Swift Code 選項,設置為Yes,如下圖:
設置編譯選項老工程的話是沒有上面的設置的,如下圖設置即可:
2.在橋接文件中引入Charts
如下圖:
3、橋接文件和開啟混編配置。如果后續報錯,可以再刪掉
4.在ViewController.m中引入相關頭文件
如下圖:
引入完成之后,編譯一下,如果有錯,Clean一下再次編譯,編譯沒有錯誤說明導入成功.
項目集成使用中的一些報錯
- dyld: Library not loaded: @rpath/Charts.framework/Charts
說明 程序里面有動態庫。需要配置xcode
targets -> general -> embedded binaries 在這里添加需要的動態庫!
我這里則需要把Charts.framework添加里面即可。
如下圖
并開啟這個設置
- 文件未找到
就算路徑對也還是報錯
解決辦法:把這兩處的都刪掉,
但是文件中要有一個 工程名-Swift.h 的命名的文件才行,否則就報錯。
- 使用XYMarkerView 彈框報錯
XYMarkerView *marker = [[XYMarkerView alloc]
initWithColor: [UIColor colorWithWhite:180/255. alpha:1.0]
font: [UIFont systemFontOfSize:12.0]
textColor: UIColor.whiteColor
insets: UIEdgeInsetsMake(8.0, 8.0, 20.0, 8.0)
xAxisValueFormatter: _chartView1.xAxis.valueFormatter];
marker.chartView = _chartView1;
marker.minimumSize = CGSizeMake(80.f, 40.f);
_chartView1.marker = marker;
**使用XYMarkerView 時一直報錯,查找不到:**
找到了文件
這個位置也是醉了,不管了,直接拖到新工程中。
#import "ChartsDemo-Swift.h"
運行報錯
把文件中原來的 字符串“ChartDome” 都換成自己的工程名稱即可,這是一個swift轉OC的中間文件。
使用Charts 繪圖
在使用過程中關鍵所在是要熟悉 Charts中的各種屬性設置,而且大部分不同的繪圖類文件的屬性名稱代表的含義一致。
我在實際的使用中做了封裝,使用起來非常簡練、方便:
效果圖:
這幾行代碼即可搞定
SCBarChartView * bar = [[SCBarChartView alloc]initWithFrame:CGRectMake(Scale_X(10), Scale_Y(40), WIDTH-Scale_X(20), Scale_Y(350))];
bar.xArray = @[@"三月",@"四月",@"無語"];
bar.yArray = @[@30,@50,@18];
bar.colorArray = @[[UIColor colorWithRed:0.54 green:0.81 blue:0.97 alpha:1.00]];
bar.yFormat = @"";
bar.barWidth = 0.5;
bar.chartLegendTitle = @"食堂統計";
[bar initBar];
[self.sc addSubview:bar];
運用細節匯總
110%看起來很怪,可以設置隱藏起來, spaceTop是展示的Y軸的比例,如果為0則頂部的數值顯示不完整,0.05最合適。
leftAxis.spaceTop = 0.05;
對于使用柱狀圖展示百分比時。如果分母是 0,那邊x坐標軸上會出現 NaN的字樣,此時應該判斷,如果分母為0,需要把整個值設置為0.
很多數據擠在一塊?想達到動態展開?
柱形圖中
- (void)setData
{
xxxxxxxxxx
CGFloat flout = self.xArray.count/3.8; //完美的值
[_chartView1 zoomAndCenterViewAnimatedWithScaleX:flout scaleY:1 xValue:0 yValue:0 axis:0 duration:1];
}
分段圖中
- (void)setData
{
CGFloat flout = self.xArray.count/7; //完美的值
[_chartView zoomAndCenterViewAnimatedWithScaleX:flout scaleY:1 xValue:0 yValue:0 axis:0 duration:1];
}
折線圖中很值得注意的細節
折線圖的自動展開
方法跟其他類型試圖的方法一樣
CGFloat flout = xArray.count/5;
[_chartView zoomAndCenterViewAnimatedWithScaleX:flout scaleY:1 xValue:0 yValue:0 axis:0 duration:1];
X軸上的數據賦值
xAxis.valueFormatter = [[DayAxisValueTwoFormatter alloc] initForChart:_chartView :xArray];
X軸上的數據和實際Y軸上的點不對應
[xAxis setGranularity:1]; //不設置就不均分
X軸最右側的數據顯示不完全
xAxis.spaceMax = 0.5; 完美解決
隱藏Y軸和Y軸的數據
ChartYAxis *leftAxis = _chartView1.leftAxis;
leftAxis.enabled = NO;
對柱狀圖上數值加上單位
- (void)setData{
BarChartData *data = [[BarChartData alloc] initWithDataSets:dataSets];
data setValueFormatter:<#(id<IChartValueFormatter> _Nullable)#> // 具體可參照官方dome
}
值在柱狀圖的里面還是上面
- (void)initBar
{
_chartView.drawValueAboveBarEnabled = NO; //設為 YES就是在柱上,設為NO就是在柱內。
}
點擊柱子后獲取一個對應的數據?
<ChartViewDelegate>
_chartView1.delegate = self;
for (int i = start; i < _yArray.count+1; i++)
{
if (self.deptNoArray.count != 0) {
[yVals addObject:[[BarChartDataEntry alloc] initWithX:i y:[_yArray[i-1] doubleValue] data:self.deptNoArray[i-1]]];
}else{
[yVals addObject:[[BarChartDataEntry alloc] initWithX:i y:[_yArray[i-1] doubleValue]]];
}
}
- (void)chartValueSelected:(ChartViewBase *)chartView entry:(ChartDataEntry *)entry highlight:(ChartHighlight *)highlight
{
if (self.pushNextDept) { //是否可以跳轉。如果不跳轉就會彈框顯示對應的數值
NSString *deptNoStr = (NSString *)entry.data;
}
}
設置Y軸上、柱狀圖上的數字千位加分割號
Y軸上的數字千位加分割號:
NSNumberFormatter *leftAxisFormatter = [[NSNumberFormatter alloc] init];
leftAxisFormatter.minimumFractionDigits = 0;
leftAxisFormatter.maximumFractionDigits = 1;
leftAxisFormatter.negativeSuffix = self.yFormat;
leftAxisFormatter.positiveSuffix = self.yFormat;
#####下面這兩句設置是實現的關鍵
[leftAxisFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
[leftAxisFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
ChartYAxis *leftAxis = _chartView1.leftAxis;
leftAxis.labelFont = [UIFont systemFontOfSize:11.f];
leftAxis.labelCount = 8;
leftAxis.valueFormatter = [[ChartDefaultAxisValueFormatter alloc] initWithFormatter:leftAxisFormatter];
leftAxis.labelPosition = YAxisLabelPositionOutsideChart;
柱狀圖的數字千位加分割號:
BarChartData *data = [[BarChartData alloc] initWithDataSets:dataSets];
[data setValueFont:[UIFont fontWithName:@"Helvetica" size:MEDIUM_FONT]];
[data setValueFormatter:[[ChartDataFormat alloc]init]];
ChartDataFormat 類實現:
*******************************************
#import <Foundation/Foundation.h>
#import "sunCanteen-Swift.h"
@interface ChartDataFormat : NSObject
<IChartValueFormatter>
@end
#import "ChartDataFormat.h"
@implementation ChartDataFormat
- (NSString *)stringForValue:(double)value entry:(ChartDataEntry *)entry dataSetIndex:(NSInteger)dataSetIndex viewPortHandler:(ChartViewPortHandler *)viewPortHandler
{
if (value == 0) {
return @"";
}else{
NSNumberFormatter *moneyFormatter = [[NSNumberFormatter alloc] init];
moneyFormatter.positiveFormat = @"###,##0";
NSString *formatString = [moneyFormatter stringFromNumber:[NSNumber numberWithDouble:value]];
return formatString;
}
}
@end
X軸上文字很長被遮擋?
ChartXAxis *xAxis = _chartView1.xAxis;
xAxis.labelPosition = XAxisLabelPositionBottom;
xAxis.labelFont = [UIFont systemFontOfSize:11.f];
xAxis.drawGridLinesEnabled = NO;
xAxis.granularity = 1.0; // only intervals of 1 day
xAxis.labelCount = 7;
xAxis.wordWrapEnabled = YES; //文字換行
xAxis.valueFormatter = [[DayAxisValueFormatter alloc] initForChart:_chartView1 :_xArray];
#### 這是重點
[xAxis setLabelRotationAngle:30];
分段柱狀圖中不顯示數值
- (void)setData{ 中
BarChartData *data = [[BarChartData alloc] initWithDataSets:dataSets];
[data setDrawValues:NO]; // 可隱藏數值
}
分段柱狀圖中點擊不顯示/顯示陰影框
點擊分段柱狀圖任意分段,整條都是選中狀態?
- (void)initBar{
_chartView.highlightFullBarEnabled = YES;
}
不顯示/顯示陰影框?
- (void)initBar{
XYMarkerView *marker = [[XYMarkerView alloc]
initWithColor: [UIColor blackColor]
font: [UIFont systemFontOfSize:12.0]
textColor: UIColor.whiteColor
insets: UIEdgeInsetsMake(8.0, 8.0, 20.0, 8.0)
xAxisValueFormatter: _chartView.xAxis.valueFormatter];
marker.chartView = _chartView;
marker.minimumSize = CGSizeMake(80.f, 40.f);
if (self.showMask) { //需要顯示就顯示,不需要就不顯示
_chartView.marker = marker;
}
}
怎樣實現如圖中陰影框中的多條顯示數據?
1.//組裝數據
- (void)setData
{
NSMutableArray *yVals = [[NSMutableArray alloc] init];
//點擊柱狀圖上彈框顯示的具體分段文本值
NSMutableString *markStr = [NSMutableString stringWithFormat:@""];
for (int i = 0; i<self.colorTitleArray.count; i++) {
NSString *str = self.colorTitleArray[i];
if (i==0) {
[markStr appendString:[NSString stringWithFormat:@"%@",str]];
}else{
[markStr appendString:[NSString stringWithFormat:@":%@",str]];
}
}
//+++++++++++++++++++++++++++++++++
for (int i = 0; i < _yArray.count; i++){
NSDictionary *dic = _yArray[i];
NSMutableArray *yValues = [[NSMutableArray alloc]initWithCapacity:0];
for (int i = 0; i < dic.count; i++)
{
[yValues addObject:[dic objectForKey:[NSString stringWithFormat:@"%d",i]]];
}
if (self.deptNoArray.count != 0) {
NSDictionary *areaInfo = @{@"deptName":self.xArray[i],@"deptNo":self.deptNoArray[i],@"mark":markStr};
[yVals addObject:[[BarChartDataEntry alloc] initWithX:i yValues:yValues data:areaInfo]];
}else{
[yVals addObject:[[BarChartDataEntry alloc] initWithX:i yValues:yValues]];
}
}
}
2.修改 XYMarkerView.swift 中的代碼
open override func refreshContent(entry: ChartDataEntry, highlight: Highlight)
{
let entry1 = entry as! BarChartDataEntry
let markStr = entry1.data?["mark"] as! String
let markStrArray:[String] = markStr.components(separatedBy:":")
let array1 = entry1.yValues
var allMarkText = ""
for(indexs,item) in (array1?.enumerated())!{
allMarkText += "\n\(markStrArray[indexs]):\(item)"
}
print("allMarkText\(allMarkText)")
setLabel(xAxisValueFormatter!.stringForValue(entry.x, axis: nil) + allMarkText)
}
詳細的使用中的參數設置可以參考如下兩篇文章:
iOS使用Charts框架繪制—柱形圖
iOS使用Charts框架繪制折線圖
小結
以上大概就是我使用 Charts這個繪圖類庫的筆記了,如有錯誤之處,請留言指正,后續如果有新的心得總結會更新此文。另外一款繪圖第三方也很不錯AAChartKit,有純OC版和純Swift版,不像本文中的Charts是OC和Swfit的混合,集成起來有點麻煩和易出錯。