読者です 読者をやめる 読者になる 読者になる

ニペブ - iPhone / iOSアプリ開発

iPhone / iOS アプリ開発方法と技術情報、入門レベルの初心者向けの記事を書いています。

(iOS/iPhoneアプリ開発) グラフ描画ライブラリ CorePlot で円グラフに凡例 legend をつける方法

完成イメージ

円グラフが表示され、その下に凡例が表示されています。
f:id:nipe880324:20131128023541p:plain:w320

環境

xcodeのプロジェクトにCorePlotを導入する

毎度のことですが導入していない人のために、記載しておきます。
次のサイト参考にして、導入しました。
core-plotでグラフを描いてみよう。-入門編- | Developers.IO
現在は「Downloads -> CorePlot_1.4.zip」でした。

円グラフに凡例 (legend) をつける

まずは、ViewController.h を作成します。上記の過去記事の円グラフと全く同じですが再掲します。
CorePlotのヘッダを追加し、必要な変数を宣言しておきます。ここは、こうなるんだなぐらいで特に説明はないです。

//
//  PieChartViewController.h
//  TestCorePlot
//
//  Created by shojiro yanagisawa on 11/22/13.
//  Copyright (c) 2013 shojiro yanagisawa. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"

@interface PieChartViewController : UIViewController
<CPTPieChartDataSource, CPTPieChartDelegate>
{
@private
    // グラフ表示領域(この領域に円グラフを追加する)
    CPTGraph *graph;
}

// 円グラフで表示するデータを保持する配列
@property (readwrite, nonatomic) NSMutableArray *pieChartData;

@end



次に、ViewController.m を作成します。
基本は「CorePlotの過去記事」の円グラフです。
細かくコメントを記載してますのでそれを見れば大体分かると思います。

凡例を表示させるために必要なことは2つで、

// 凡例インスタンスを生成
CPTLegend *theLegend = [CPTLegend legendWithPlots:[NSArray arrayWithObject:[graph plotAtIndex:0]]];
  • 「凡例のためのデータソースメソッドの実装」
// 凡例ための文字列を返す
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index

です。
そこを中心に見れば難しくないので実装ができると思います。
実際のソースコードです。

//
//  PieChartViewController.m
//  TestCorePlot
//
//  Created by shojiro yanagisawa on 11/22/13.
//  Copyright (c) 2013 shojiro yanagisawa. All rights reserved.
//

#import "PieChartViewController.h"

@interface PieChartViewController ()

@end

@implementation PieChartViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // -----------------------
    // グラフに表示するデータを生成
    // 40%, 30%, 20%, 10%の4項目の円グラフのデータ
    // -----------------------
    self.pieChartData = [NSMutableArray arrayWithObjects:
                         [NSNumber numberWithDouble:40.0],
                         [NSNumber numberWithDouble:30.0],
                         [NSNumber numberWithDouble:20.0],
                         [NSNumber numberWithDouble:10.0],
                         nil];

    // -----------------------
    // ホスティングビュー
    // -----------------------
    // ホスティングビューを生成
    CPTGraphHostingView *hostingView =
    [[CPTGraphHostingView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
    // 画面にホスティングビューを追加
    [self.view addSubview:hostingView];

    // -----------------------
    // 円グラフ
    // -----------------------
    // グラフを生成
    graph = [[CPTXYGraph alloc] initWithFrame:hostingView.bounds];
    // ホスティングビューにグラフを追加
    hostingView.hostedGraph = graph;
    // グラフのタイトルを設定
    graph.title          = @"Graph Title";
    // グラフの軸を設定
    // 今回は円グラフなので、グラフの軸は使用しない
    graph.axisSet = nil;
    
    // -----------------------
    // 円グラフ
    // -----------------------
    // 円グラフのインスタンスを生成
    CPTPieChart *pieChart = [[CPTPieChart alloc] init];
    // 円グラフの半径
    pieChart.pieRadius = 80.0;
    // データソースとデリゲートを設定
    pieChart.dataSource = self;
    pieChart.delegate = self;
    // グラフに円グラフを追加
    [graph addPlot:pieChart];
    
    // -----------------------
    // 凡例(legend)
    // -----------------------
    // 凡例インスタンスを生成
    CPTLegend *theLegend = [CPTLegend legendWithPlots:[NSArray arrayWithObject:[graph plotAtIndex:0]]];
    // 凡例の列数を指定
    theLegend.numberOfColumns = 2;
    // 凡例の表示部分の背景色を指定
    theLegend.fill = [CPTFill fillWithColor:[CPTColor whiteColor]];
    // 凡例の外枠線の表示をする
    theLegend.borderLineStyle = [CPTLineStyle lineStyle];
    // 凡例の外枠線の角丸の程度
    theLegend.cornerRadius = 5.0;

    // 作成した凡例をグラフに追加
    graph.legend = theLegend;
    // 凡例の位置をグラフの下側に設定
    // (他にもCPTRectAnchor...で上側や右側などいろいろな場所に配置可能)
    graph.legendAnchor = CPTRectAnchorBottom;
    // 凡例の位置を調整
    graph.legendDisplacement = CGPointMake(30, -30);
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}


#pragma mark -
#pragma mark Plot Data Source Methods

// グラフに使用するデータの数を返す
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    return [self.pieChartData count];
}

// グラフに使用するデータの値を返す
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    // 円グラフのデータ量を返す
    return [self.pieChartData objectAtIndex:index];
}

// グラフの各項目にラベルをつける
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
{
    CPTTextLayer *label = [[CPTTextLayer alloc] initWithText:
                           [NSString stringWithFormat:@"index: %lu\ndata: %@", (unsigned long)index, [self.pieChartData objectAtIndex:index]]];
    CPTMutableTextStyle *textStyle = [label.textStyle mutableCopy];
    
    textStyle.color = [CPTColor lightGrayColor];
    label.textStyle = textStyle;
    return label;
}

// 円グラフの中心からoffset値だけ外側に項目を切り出す
-(CGFloat)radialOffsetForPieChart:(CPTPieChart *)piePlot recordIndex:(NSUInteger)index
{
    CGFloat offset = 0.0;
    
    if ( index == 0 ) {
        offset = piePlot.pieRadius / 8.0;
    }
    
    return offset;
}

// 凡例ための文字列を返す
-(NSString *)legendTitleForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)index
{
    return [[NSString alloc] initWithFormat:@"index: %lu", (unsigned long)index];
}

#pragma mark Delegate Methods
// 円グラフの各項目をタップしたときのイベント
-(void)pieChart:(CPTPieChart *)plot sliceWasSelectedAtRecordIndex:(NSUInteger)index
{
    // グラフタイトルにタップされた各項目のインデックス番号を設定
    graph.title = [NSString stringWithFormat:@"Selected index: %lu", (unsigned long)index];
}

@end


円グラフや棒グラフなどCorePlotのサンプルのソースコードGithubに置いてあります。よろしければ、覗いてみてください。
yanagi0324/test-core-plot · GitHub

参考情報


分かりづらい箇所やご質問などありましたら、 コメントやメールアドレスにご連絡いただけると嬉しいです。