繪圖-iOS在OC項目中集成Charts繪制圖表框架

前言

最近OC項目中使用到了charts做圖標繪制,確實是一個很酷并且功能強大的類庫。里面包含了各式各樣的圖標樣式,但是使用的是Swift語言編寫,所以就涉及到混編的一些操作配置。

你可以通過兩種方式集成進你的項目中:

  • 下載后手動添加 (本文主講)
  • Cocopods的方式集成

Charts下載地址

注意一下使用條件:值得注意的是工程的 Tagerts 最低設置 8.0

解壓后的文件夾里面的內容是這個樣子的,如下圖:


導入工程中的步驟

  • 新建工程

    新建工程,取名為ImportChartsDemo.

  • 復制Charts整個文件到ImportChartsDemo工程中

    就是把上圖中解壓后的文件(剔除紅色框中的文件,當然也可以剔除其他一些沒有用的文件,由于我沒有剔除多余的文件,并最終集成成功,所以就暫時視除了紅框內的文件都需要)拷貝到ImportChartsDemo主工程文件夾下。

  • 導入Charts.xcodeproj

    右擊項目,選擇 -> Add Files to”xx”, 在彈出的選擇文件框中選擇”Charts.xcodeproj”(注意:不要選擇文件夾)。

  • 添加Charts.framework

找到General->Embedded Binaries,點擊+號添加Charts.framework,如下圖:

Embedded Binaries位置

添加的iOS的framework,如下圖:


添加Charts.framework
  • 建立OC和Swift的橋接文件
    在ImportChartsDemo工程中新建一個Swift文件,名字隨便取,這時候會提示是否建立橋接文件,直接選Create Bridging Header 選項,如下圖:
    建立橋接文件

新建完成后,會自動生成一個橋接文件,如下圖:


自動生成的橋接文件
  • 設置編譯選項及引入Charts

    1.設置編譯選項

    找到Build Settings -> Embedded Content Contains Swift Code 選項,設置為Yes,如下圖:


    設置編譯選項

    老工程的話是沒有上面的設置的,如下圖設置即可:


2.在橋接文件中引入Charts

如下圖:


引入Charts

3、橋接文件和開啟混編配置。如果后續報錯,可以再刪掉

4.在ViewController.m中引入相關頭文件
如下圖:

引入頭文件

引入完成之后,編譯一下,如果有錯,Clean一下再次編譯,編譯沒有錯誤說明導入成功.

項目集成使用中的一些報錯

  • dyld: Library not loaded: @rpath/Charts.framework/Charts

FAEFA9CE-2914-4C86-9334-C9728C47715F.png

說明 程序里面有動態庫。需要配置xcode
targets -> general -> embedded binaries 在這里添加需要的動態庫!
我這里則需要把Charts.framework添加里面即可。
如下圖

并開啟這個設置
4AC49923-AB62-40B3-AE9C-84C865C8D961.png

  • 文件未找到

就算路徑對也還是報錯

解決辦法:把這兩處的都刪掉,

但是文件中要有一個 工程名-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.

很多數據擠在一塊?想達到動態展開?

自動展開.gif

柱形圖中

- (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的混合,集成起來有點麻煩和易出錯。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容