PHP4 - グラフを作ろう! (gd/JpGraph編)
PHP でいろいろとプログラムを作っていると、あるデータをグラフ化したくなってきます。そこで、グラフを作成するモジュールを探して使ってみることにします。ここでの JpGraphの設定は PHP4用です。PHP5を利用する場合、「PHP5/MySQL5/JpGraphで Web アプリケーション」 を参照してください。
PHPの状態と GD モジュール
PHP で、グラフを作成するのに便利なモジュールとして JpGraph, PHPlot があります。まず、これを利用するのに GD モジュールを有効にしなくてはなりません。
PHP の現在の状態を確認してください。
<?php phpinfo(); ?>
その際、GD
モジュールが enabled
になっているか確認してください。有効になっていれば、以下のインストール作業は必要ありません。次のJpGraph, PHPlot の節に進んでください。
PHP で GD
モジュールが有効でない場合、必要なパッケージを入手しインストールしなくてはなりません。システムを確認し、以下のリストの中で足りないものをインストールしてください。
GD Graphics Library | Thomas Boutell氏の作成した、線や多角形、円を描画するためのライブラリ | http://www.boutell.com/gd/ |
PNG graphics library | PNG グラフィックスフォーマット用のライブラリ | http://www.libpng.org/pub/png |
zlib compression library | zlib 汎用圧縮ライブラリ | http://www.gzip.org/zlib/ |
FreeType | TrueTypeフォントをレンダリングするライブラリ | http://www.freetype.org/ |
JPEG library | JPEG グラフィックスフォーマット用のライブラリ | ftp://ftp.uu.net/graphics/jpeg/ |
インストール手順 (スーパーユーザーで作業)
# gzip -dc zlib-1.1.4.tar.gz | tar xf - # cd zlib-1.1.4 # ./configure (ダイナミックライブラリを作りたければコマンドラインオプション --shared を指定しておく) # make # make install # gzip -dc libpng-1.2.7.tar.gz | tar xf - # cd libpng-1.2.7 # cp scripts/makefile.OS Makefile (OS は、インストールする OS のタイプを指定:linux, solaris ...) # make # make install # gzip -dc jpegsrc.v6b.tar.gz | tar xf - # cd jpeg-6b # ./configure --enable-static (ダイナミックライブラリを作りたければコマンドラインオプション --enable-shared を指定) # make # make install # gzip -dc freetype-2.1.9.tar.gz | tar xf - # cd freetype-2.1.9 # ./configure --enable-static # make # make install # gzip -dc gd-2.0.28.tar.gz | tar xf - # cd gd-2.0.28 # ./configure --without-libiconv-prefix (iconv を指定したければコマンドラインオプション --with-libiconv-prefix=PATH を指定) (png, jpeg, freetype をきちんと指定したければコマンドラインオプション --with-????=PATH を指定) ... ** Configuration summary for gd 2.0.28: Support for PNG library: yes Support for JPEG library: yes Support for Freetype 2.x library: yes Support for Xpm library: yes Support for pthreads: yes ... # make # make install
PHP + Apache のインストール
基本的なインストール方法は、「PHP と PostgreSQL/MySQL で Web アプリケーションを!」を参照してください。ここでは、PHP で GD モジュールを有効にするコンフィグレーションを重点に記述します。
Apache はDSO(Dynamic Shared Object)対応でコンパイルし、インストールしてください。
PHP のソースの展開とコンパイル(DSOを作成する)
# gzip -dc php-4.3.9.tar.gz | tar xf - # cd php-4.3.9 # ./configure --with-pgsql=/usr/local/pgsql --with-mysql=/usr/local/mysql \ > --with-apxs2=/usr/local/apache2/bin/apxs --enable-track-vars \ > --enable-mbstring --enable-mbregex --enable-zend-multibyte \ > --with-gd=/usr/local --with-freetype-dir=/usr/local --with-jpeg-dir=/usr/local \ > --with-png-dir=/usr/local --with-zlib-dir=/usr/local --enable-gd-native-ttf \ > --enable-gd-jis-conv # make # make install
コマンドラインオプションの説明(必要なもの選んでください)
--with-gd[=DIR] |
GD パッケージをインストールしたディレクトリを指定。DIR を指定しなかった場合、バンドルされている GD を使用。 |
--with-jpeg-dir[=DIR] |
libjpeg パッケージをインストールしたディレクトリを指定 |
--with-png-dir[=DIR] |
libpng パッケージをインストールしたディレクトリを指定 |
--with-zlib-dir[=DIR] |
libz パッケージをインストールしたディレクトリを指定 |
--with-xpm-dir[=DIR] |
libXpm パッケージをインストールしたディレクトリを指定 |
--with-ttf[=DIR] |
FreeType 1.x パッケージをインストールしたディレクトリを指定 |
--with-freetype-dir[=DIR] |
FreeType 2 パッケージをインストールしたディレクトリを指定 |
--with-t1lib[=DIR] |
T1lib パッケージをインストールしたディレクトリを指定 |
--enable-gd-native-ttf |
TrueType string function を有効にする |
--enable-gd-jis-conv |
JIS-mapped Japanese font を有効にする |
インストールが完了し、Apache を再起動したなら、PHP の現在の状態が以下のようになっていることを確認してください。
JpGraph, PHPlot クラス・ライブラリー
ここでは、二つのライブラリを紹介します。どのライブラリーを使ったらよいかは、JpGraph は商用利用で有料ですが、PHPlot は商用での利用が可能です。しかし、PHPlot は日本語がうまく扱えません(使い方を知らないだけかも)。
● JpGraph
まず、JpGraph を使ってみましょう。 必要なモジュールをダウンロードしてインストールします。Windowsで使用したいなら「Windows版 PHP環境でグラフを作ろう!」を、Solaris 10 や PHP5 で使用したいなら「Solaris 10 に PHP5 と MySQL5 をインストール」や「PHP5/MySQL5/JpGraphで Web アプリケーション」 を参照してください。
JpGraph | http://www.aditus.nu/jpgraph/ |
sazanami フォントを入手 | http://sourceforge.jp/projects/efont/files/ |
JpGraph のライブラリは、どこに置いても構いませんが PHP がサーチできるパス (include_path
)に置くか、インストールしたディレクトリを php.ini
の include_path
に追加すると良いでしょう。 ここでは、include_path = ".:/usr/local/lib/php"
となっているとして、/usr/local/lib/php/JpGraph
にライブラリをインストール(コピー)します。
JpGraph 1.22 の場合:
JpGraph の設定は、キャッシュのディレクトリと TrueType フォントが含まれるディレクトリを指定します。デフォルトでは情報処理推進機構の日本語フォント(GRASS国際化版に付属)が指定されているためダウンロードしてインストールします。Linuxの場合、ディストリビューションによっては既に含まれている場合があります。
# gzip -dc grass5.0.3_i686-pc-linux-i18n-ipafull-gnu_bin.tar.gz | tar xf - ./fonts # mkdir -p /usr/local/fonts/truetype # cp fonts/*.ttf /usr/local/fonts/truetype/
JpGraph の設定設定(jpg-config.inc.php
で、キャッシュのディレクトリと TrueType フォントが含まれるディレクトリと日本語のフォントを指定)
# gzip -dc jpgraph-1.22.tar.gz | tar xf - # cp -rp jpgraph-1.22/src /usr/local/lib/php/JpGraph # edit /usr/local/lib/php/JpGraph/jpg-config.inc.php 39行目 DEFINE("CACHE_DIR", "/tmp/jpgraph_cache/"); DEFINE("TTF_DIR", "/usr/X11R6/lib/X11/fonts/truetype/"); DEFINE("MBTTF_DIR", "/usr/local/fonts/truetype/"); # mkdir /tmp/jpgraph_cache # chmod 777 /tmp/jpgraph_cache
これで設定は完了です。
簡単な円グラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーの DocumentRoot下に置き、ブラウザーから実行すると円グラフが表示されます。JpGraph で日本語を扱うには、文字コードをUTF-8 にする必要があります。以下のサンプルでは入力漢字コードは、ローマ数字などを扱う場合などを考慮して eucJP-win
としています(つまり、以下のサンプルは EUC
で書かれているので mb_convert_encoding
を利用して UTF-8
にしていますということ、サンプルが Shift-JIS
で書かれていれば sjis-win
を UTF-8
にするようにし、UTF-8
で書かれていれば変換の必要はありません)。
※ 異機種間で漢字変換を行うと、当然のことながら漢字コード特有の特殊文字や機種依存文字の変換はうまく行えません。
<?php // 使用するグラフを読み込む require_once("JpGraph/jpgraph.php"); require_once("JpGraph/jpgraph_pie.php"); require_once("JpGraph/jpgraph_pie3d.php"); // データの設定 $data_yes = mb_convert_encoding("好き", "UTF-8", "eucJP-win"); $data_no = mb_convert_encoding("嫌い", "UTF-8", "eucJP-win"); $data_unkown = mb_convert_encoding("わからない", "UTF-8", "eucJP-win"); $data_none = mb_convert_encoding("無回答", "UTF-8", "eucJP-win"); $data_legends = array($data_yes, $data_no, $data_unkown, $data_none); $data = array( 43, 15, 32, 10); // グラフオブジェクトの生成 $graph = new PieGraph(350,300,"auto"); $title = mb_convert_encoding("にこにこ村について","UTF-8","eucJP-win"); $graph->title->Set($title); $graph->title->SetFont(FF_GOTHIC, FS_NORMAL, 16); $graph->legend->Pos(0.05, 0.95, "right", "bottom"); $graph->legend->SetFont(FF_GOTHIC, FS_NORMAL); $pie = new PiePlot3D($data); $pie->SetSize(0.4); $pie->SetCenter(0.5,0.5); $pie->SetLegends($data_legends); $graph->Add($pie); // イメージフォーマット $graph->img->SetImgFormat('gif'); // グラフの表示 $graph->Stroke(); ?>
今度は、折線グラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーのDocumentRoot下に置き、ブラウザーから実行すると折線グラフが表示されます。
<?php // 使用するグラフ require_once("JpGraph/jpgraph.php"); require_once("JpGraph/jpgraph_line.php"); require_once("JpGraph/jpgraph_canvas.php"); // データ $labelx = array("1999", "2000", "2001", "2002", "2003", "2004"); $data1 = array( 1683, 1719, 1754, 1883, 1502, 1677); $data2 = array( 1261, 996, 875, 794, 982, 1140); $data3 = array( 101, 230, 380, 513, 827, 1843); // Y軸用のコールバック関数 function yScaleCallback($aVal) { return number_format($aVal); } // グラフオブジェクトの生成 $graph = new Graph(500,400,"auto"); // 画像フォーマット $graph->img->SetImgFormat("jpeg"); $graph->img->SetQuality(80); // マージン left, right, top, bottom $graph->img->SetMargin(60,40,70,40); $graph->img->SetAntiAliasing(); $graph->SetScale("textint"); $graph->SetFrame(false); $graph->SetColor('lightblue'); // タイトル $title = mb_convert_encoding("にこにこ村交通事情","UTF-8","eucJP-win"); $graph->title->Set($title); $graph->title->SetFont(FF_GOTHIC, FS_NORMAL, 14); // X,Y軸 $graph->xaxis->SetTickLabels($labelx); $graph->yaxis->SetLabelFormatCallback('yScaleCallback'); $graph->yaxis->SetTextLabelInterval(2); $graph->yaxis->HideZeroLabel(); $graph->yaxis->SetTitleMargin(55); $titley = mb_convert_encoding("人","UTF-8","eucJP-win"); $graph->yaxis->title->Set($titley); $graph->yaxis->title->SetFont(FF_GOTHIC, FS_NORMAL); $titlex = mb_convert_encoding("年度","UTF-8","eucJP-win"); $graph->xaxis->title->Set($titlex); $graph->xaxis->title->SetFont(FF_GOTHIC, FS_NORMAL); // グリッド $graph->xgrid->Show(true,false); $graph->ygrid->SetFill(true,'#EFEFFF@0.5','#DDEEFF@0.5'); // 凡例 $graph->legend->Pos(0.5, 0.08, "center", "top"); $graph->legend->SetLayout(LEGEND_HOR); $graph->legend->SetFont(FF_GOTHIC, FS_NORMAL); $graph->legend->SetShadow(false); $graph->legend->SetLineWeight(1); $graph->legend->SetColor('black','darkgray'); $graph->legend->SetFillColor('lightblue'); // 陸の交通手段 $legend1 = mb_convert_encoding("陸","UTF-8","eucJP-win"); $p1 = new LinePlot($data1); $p1->mark->SetType(MARK_FILLEDCIRCLE); $p1->mark->SetFillColor("blue"); $p1->mark->SetWidth(3); $p1->SetColor("blue"); $p1->SetCenter(); $p1->SetLegend($legend1); $graph->Add($p1); // 海の交通手段 $legend2 = mb_convert_encoding("海","UTF-8","eucJP-win"); $p2 = new LinePlot($data2); $p2->mark->SetType(MARK_SQUARE); $p2->mark->SetFillColor("red"); $p2->mark->SetWidth(4); $p2->SetColor("red"); $p2->SetCenter(); $p2->SetLegend($legend2); $graph->Add($p2); // 空の交通手段 $legend3 = mb_convert_encoding("空","UTF-8","eucJP-win"); $p3 = new LinePlot($data3); $p3->mark->SetType(MARK_DIAMOND); $p3->mark->SetFillColor("orange"); $p3->mark->SetWidth(6); $p3->SetColor("orange"); $p3->SetCenter(); $p3->SetLegend($legend3); $graph->Add($p3); // コメント $message = mb_convert_encoding("いろいろな交通手段","UTF-8","eucJP-win"); $t1 = new Text($message); $t1->Pos(0.15,0.7); $t1->SetOrientation("h"); $t1->SetFont(FF_GOTHIC, FS_NORMAL); $t1->SetBox("white","black",'gray'); $t1->SetColor("black"); $graph->AddText($t1); // グラフの描画 $graph->Stroke(); ?>
最後に、レーダーグラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーのDocumentRoot下に置き、ブラウザーから実行するとレーダーグラフが表示されます。
<?php require_once("JpGraph/jpgraph.php"); require_once("JpGraph/jpgraph_radar.php"); // データ
$aryData = array(7,10,6,8,9); // 軸タイトル $aryTitle = array( mb_convert_encoding("走り", "UTF-8","eucJP-win"), mb_convert_encoding("乗り心地", "UTF-8","eucJP-win"), mb_convert_encoding("燃費", "UTF-8","eucJP-win"), mb_convert_encoding("操作性", "UTF-8","eucJP-win"), mb_convert_encoding("デザイン", "UTF-8","eucJP-win") ); // レーダーグラフの初期化 $graph = new RadarGraph(300,250,"auto"); $graph->img->SetAntiAliasing(); // 背景の設定 $graph->SetColor("white"); $graph->SetFrame(false);
// グラフの描画位置
$graph->SetCenter(0.5,0.55); // 軸の設定 $graph->axis->SetFont(FF_GOTHIC,FS_NORMAL); $graph->axis->title->SetFont(FF_GOTHIC,FS_NORMAL); $graph->axis->SetColor("#207870"); // グリッドの設定 $graph->grid->SetLineStyle("dotted"); $graph->grid->SetColor("gray"); $graph->grid->Show(); $graph->HideTickMarks(); // タイトルの設定 $graph->title->Set(mb_convert_encoding("ニコニコカー","UTF-8","eucJP-win")); $graph->title->SetFont(FF_GOTHIC,FS_NORMAL, 13); $graph->title->SetColor("#406898"); $graph->SetTitles($aryTitle); // プロットデータの作成 $plot = new RadarPlot($aryData); $plot->SetColor("#ff5588","#ffeeee"); //$plot->SetFill(false); $plot->SetLineWeight(2); // プロットデータの追加
$graph->Add($plot); // グラフの描画 $graph->Stroke(); ?>
● PHPlot
SetUseTTF()
, SetTTFPath()
, SetDefaultTTFont()
といったメソッドがあるので、日本語の TrueType フォントを使ってみようかと思ったのですがうまく動作しないのでまだ仮として記述します。気合を入れてチェックすればよいのですが時間が無いので適当な時期とともに以下の内容を変えていきます。
必要なモジュールをダウンロードしてインストールします。
PHPlot | http://www.phplot.com/ |
PHPlot のライブラリは、どこに置いても構いませんが PHP がサーチできるパス (include_path
)に置くか、インストールしたディレクトリを php.ini
の include_path
に追加すると良いでしょう。 ここでは、include_path = ".:/usr/local/lib/php"
となっているとして、/usr/local/lib/php/PHPlot
にライブラリをインストール(コピー)します。
# bunzip2 phplot-5.0rc1.tar.bz2 # tar xf phplot-5.0rc1.tar # cd phplot # mkdir /usr/local/lib/php/PHPlot # cp *.php /usr/local/lib/php/PHPlot/ # chmod 644 /usr/local/lib/php/PHPlot/*.php
これで設定は完了です。簡単な棒グラフを作ってみましょう。以下のプログラムを適当なファイル名で Web サーバーのDocumentRoot下に置き、ブラウザーから実行すると棒グラフが表示されます。
<?php // ライブラリの読み込み require_once('PHPlot/phplot.php'); // データの設定 $data = array(
array('1980', 20, 60, 45), array('1985', '', 40, 20), array('1990', 10, 55, 10), array('1995', 30, 65, 20), array('2000', 50, 50, 40), array('2005', 70, 45, 60), ); // グラフオブジェクトの生成 $graph = new PHPlot(450,280); $graph->SetDataType("text-data"); $graph->SetDataValues($data); $graph->SetXTitle("Year"); $graph->SetYTitle("Output"); $graph->SetYTickIncrement(10); $graph->SetPlotType("bars"); $graph->SetXLabelAngle(0); $graph->SetLegend(array("Japan", "USA", "EC")); $graph->SetNewPlotAreaPixels(40,100,400,240); $graph->SetPlotAreaWorld(0,0,7,80); // グラフの表示 $graph->DrawGraph(); ?>
Webページに組み込む場合の注意
グラフを出力するプログラムは、GIF, JPEG
といった画像を出力します。そのままでは、Webページに画像を貼り付けられないので <img>
タグを使用します。グラフを出力するプログラムが graph.php
という名前だったとすると、<img src="graph.php" alt="graph">
のように <img>
タグにプログラムを記述します。しかし、<img> タグで指定しているので、エラーの際はメッセージを出力して終了するのではなくエラー画像ファイルを用意しておき readfile, fpassthru
関数で出力するとよいでしょう。
<?php
// クラスの読み込みなど
require_once("JpGraph/jpgraph.php");
require_once("...");
define("IMG_NODATA", "/.../images/nodata.gif");
// データの設定
$data = <データの取得>
if (データが取得できた) {
// グラフを作成
$graph = new Graph(500,400,"auto");
...
// グラフを出力
$graph->Stroke();
} else {
// 用意しておいたエラー画像を出力
$fp = fopen(IMG_NODATA, "r");
fpassthru
($fp);
fclose($fp);
}
?>
ここで fopen
でエラーだった場合どうすればよいのかということになる。そこまで信頼のおけない環境の場合、nodata.gif
を base64 でエンコードしたデータを保持しておきエラーの場合にはデコードして header("Content-type: image/gif")
としてプリントするといった方法をとるとよい。これならファイルをオープンするなどの処理がいらないので確実にエラー画像を出力できます(実際にJpGraph はこの方法でエラー画像を出力しています)。