Image_Graphによる円グラフ作成

次は円グラフを作ります。同じようにベースサンプルから

http://pear.veggerby.dk/samples/code/id/plot_pie_rest/

を利用します。


環境整備

Pearの設定とフォント設定を行って、サンプルを動く状況にします。

凡例が表示されていません!

結論からいいますとライブラリのバグになります。

凡例表示を直す

ソースコードを読んでいくと凡例表示の場所を特定しました。

Graph/Plot/Pie.php

    /**
     * Draw a sample for use with legend
     *
     * @param array $param The parameters for the legend
     * @access private
     */
    function _legendSample(&$param)

の関数になります。この関数が原因で表示できていません。

細かい関数の動きがわからないので、動いている他の凡例表示部分からコピーして動かしてみました。

元にしたコードは Graph/Plot.php です。

ちょっとおかしいですが動きました。こちらとの差を調べてみました。

    $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
    $this->_clip(true);

...

    $this->_clip(false);
    $this->_canvas->endGroup();

この辺の処理が Plot.php にはなくて、Pie.php にはありますね。ここをコメントアウトしてみます。

//    $this->_canvas->startGroup(get_class($this) . '_' . $this->_title);
//    $this->_clip(true);

...

//    $this->_clip(false);
//    $this->_canvas->endGroup();

正常に描画できるようになりました!

タイトルとフォントサイズを変更

-   $Font->setSize(8);
+   $Font->setSize(12);

-      Image_Graph::factory('title', array('Pie Chart Sample', 12)),
+      Image_Graph::factory('title', array('円グラフサンプル', 12)),

ファイルの保存はUTF8Nで!


タイトル文字がはみ出ましたので修正

// setup the plotarea, legend and their layout
$Graph->add(
   Image_Graph::vertical(
      Image_Graph::factory('title', array('円グラフサンプル', 12)),        
      Image_Graph::vertical(
         $Plotarea = Image_Graph::factory('plotarea'),
         $Legend = Image_Graph::factory('legend'),
         70
      ),
      5
   )
);

ここの内容なのですが、addでグラフに要素を追加します。その後にverticalで縦に2分割して1つ目にタイトル文字、2つ名にさらに縦に分離してグラフと凡例を表示しています。

// setup the plotarea, legend and their layout
$Graph->add(
   Image_Graph::vertical(
      (1)の部分,        
      Image_Graph::vertical(
         (2)の部分,
         (3)の部分,
         70
      ),
      5
   )
);

verticalの第一引数は1個目の要素、第二引数は2個目の要素、第三引数が1個目の引数の割合になります。

// setup the plotarea, legend and their layout
$Graph->add(
   Image_Graph::vertical(
      Image_Graph::factory('title', array('円グラフサンプル', 12)),        
      Image_Graph::vertical(
         $Plotarea = Image_Graph::factory('plotarea'),
         $Legend = Image_Graph::factory('legend'),
         85
      ),
      7
   )
);

タイトルを7%、グラフも85%に変更しました。


数値表示修正

// create a Y data value marker
$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_PCT_Y_TOTAL);
// fill it with white
$Marker->setFillColor('white');
// and use black border
$Marker->setBorderColor('black');
// and format it using a data preprocessor
$Marker->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.1f%%'));
$Marker->setFontSize(7);

これが元の設定ですが、ボーダーカラーをなくして、フォントサイズを大きくします。

$Marker->setBorderColor('transparent');
$Marker->setFontSize(11);

注意点としてsetFillColorは白のままになります。透明にすると文字の下にグラフから伸びている線が表示されてしまいます。

めり込み修正

グラフに数値がめり込んでいるので修正します。

// create a pin-point marker type
$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker));

ここが数値の設定なので、最後の20がグラフからの距離になります。ここでは25に変更しました。

// create a pin-point marker type
$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(25, &$Marker));

本当は30ぐらいにして、凡例のサイズも調整した方が全部線が見えてよいのかもしれませんがその分グラフが小さくなりますので、このままいきます。


すべてのデータを表示する

データは9個セットしていますが、表示されているデータは6個になります。これは特定以下の数値をまとめて表示する機能を利用しているためになります。

$Plot->setRestGroup(11, 'Other animals');

名前から調べればわかるのですが、上記の設定で11以下の物をまとめる設定になります。少し大きいので5に変更すると以下になります。

すべてのデータを表示させたい場合にはコメントアウトします。ただし凡例が9個目のFlyが3行目に追い出されているため凡例のサイズを調整するか、フォントサイズを調整する必要があります。

//$Plot->setRestGroup(11, 'Other animals');


サイズ調整

// create the graph
$Graph =& Image_Graph::factory('graph', array(400, 400));

・・・

// setup the plotarea, legend and their layout
$Graph->add(
   Image_Graph::vertical(
      Image_Graph::factory('title', array('円グラフサンプル', 12)),        
      Image_Graph::vertical(
         $Plotarea = Image_Graph::factory('plotarea'),
         $Legend = Image_Graph::factory('legend'),
         80
      ),
      7
   )
);

今回は縦幅を400ピクセルにして、凡例エリアを広げました。もしくは横長の画像にできる場合には凡例エリアを下ではなく右に表示する形にする形にするとすっきりします。


色調整

// set a standard fill style
$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array');
$Plot->setFillStyle($FillArray);
$FillArray->addColor('green@0.2');
$FillArray->addColor('blue@0.2');
$FillArray->addColor('yellow@0.2');
$FillArray->addColor('red@0.2');
$FillArray->addColor('orange@0.2');
$FillArray->addColor('black@0.2', 'rest');

上記の場所が初期設定の色になります。restと付いている場所が元々その他の場所になります。

// set a standard fill style
$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array');
$Plot->setFillStyle($FillArray);
$FillArray->addColor('green@0.2');
$FillArray->addColor('blue@0.2');
$FillArray->addColor('yellow@0.2');
$FillArray->addColor('red@0.2');
$FillArray->addColor('orange@0.2');
$FillArray->addColor('black@0.2');

$FillArray->addColor('green@0.6');
$FillArray->addColor('blue@0.6');
$FillArray->addColor('yellow@0.6');
$FillArray->addColor('red@0.6');
$FillArray->addColor('orange@0.6');
$FillArray->addColor('black@0.6');

$FillArray->addColor('green@1');
$FillArray->addColor('blue@1');
$FillArray->addColor('yellow@1');
$FillArray->addColor('red@1');
$FillArray->addColor('orange@1');
$FillArray->addColor('black@1');

とりあえずrestはいらなそうだったので、削除しました。また色ですが名前で指定するのでちょっとわかりにくいですね。今度色見本を作成したいと思います。

また@より後ろは不透明度になり、数値が小さいほど透明に近くなります。ここでは元の色をコピーして色を濃くしました。実際にデータが何個入ってくるかわからないのでここは多めに指定した方がよいと思います。

また、データ自体は合計で100にする必要がなく、自動的に割合に変換してくれますが、実際には合計を100%にしてデータを渡した方がその他でまとめやすいと思います。


最後に

凡例がでないのにはちょっとあせりましたが、それ以外は比較的簡単に利用することができそうです。

円の中心が開いていますが、ここの指定は以下の場所になります。数値を0に設定すれば普通の円グラフになりますが、多少開いていた方が見やすいとは思います。

$Plot->explode(10);

最終的なソース

<?php
/**
 * Usage example for Image_Graph.
 * 
 * Main purpose: 
 * Show pie chart
 * 
 * Other: 
 * None specific
 * 
 * $Id: plot_pie_rest.php,v 1.1 2005/10/13 20:18:27 nosey Exp $
 * 
 * @package Image_Graph
 * @author Jesper Veggerby <pear.nosey@veggerby.dk>
 */

ini_set('include_path', './PEAR');
require_once 'Image/Graph.php';

// create the graph
$Graph =& Image_Graph::factory('graph', array(400, 400));
// add a TrueType font
$Font =& $Graph->addNew('font', 'fonts/ipagp.ttf');
// set the font size to 11 pixels
$Font->setSize(12);

$Graph->setFont($Font);

// setup the plotarea, legend and their layout
$Graph->add(
   Image_Graph::vertical(
      Image_Graph::factory('title', array('円グラフサンプル', 12)),        
      Image_Graph::vertical(
         $Plotarea = Image_Graph::factory('plotarea'),
         $Legend = Image_Graph::factory('legend'),
         80
      ),
      7
   )
);
$Legend->setPlotArea($Plotarea);
$Plotarea->hideAxis();

// create the dataset
$Dataset =& Image_Graph::factory('dataset', 
    array(
        array(
            'Monkey' => 12,
            'Cat' => 14,
            'Dog' => 13,
            'Platypuss' => 29,
            'Spider' => 5,
            'Elephant' => 9,
            'Gerbil' => 3,
            'Mouse' => 19,
            'Fly' => 11
        )
    )
);

// create the 1st plot as smoothed area chart using the 1st dataset
$Plot =& $Plotarea->addNew('Image_Graph_Plot_Pie', $Dataset);

//$Plot->setRestGroup(5, 'Other animals');

$Plot->Radius = 2;
    
// set a line color
$Plot->setLineColor('gray');

// set a standard fill style
$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array');
$Plot->setFillStyle($FillArray);
$FillArray->addColor('green@0.2');
$FillArray->addColor('blue@0.2');
$FillArray->addColor('yellow@0.2');
$FillArray->addColor('red@0.2');
$FillArray->addColor('orange@0.2');
$FillArray->addColor('black@0.2');

$FillArray->addColor('green@0.6');
$FillArray->addColor('blue@0.6');
$FillArray->addColor('yellow@0.6');
$FillArray->addColor('red@0.6');
$FillArray->addColor('orange@0.6');
$FillArray->addColor('black@0.6');

$FillArray->addColor('green@1');
$FillArray->addColor('blue@1');
$FillArray->addColor('yellow@1');
$FillArray->addColor('red@1');
$FillArray->addColor('orange@1');
$FillArray->addColor('black@1');

$Plot->explode(10);

// create a Y data value marker
$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_PCT_Y_TOTAL);
// fill it with white
$Marker->setFillColor('white');
// and use black border
$Marker->setBorderColor('transparent');
// and format it using a data preprocessor
$Marker->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.1f%%'));
$Marker->setFontSize(11);

// create a pin-point marker type
$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(25, &$Marker));
// and use the marker on the plot
$Plot->setMarker($PointingMarker);

// output the Graph
$Graph->done();