お客様からこんな依頼をいただきました。
入力フォームに入力した値を基に、結果ページとしてグラフを描画。
結果ページをグラフごとPDFとしてダウンロードさせたい。
実現までに調べたこと、納品までに悩んだ点等をご紹介いたします!
PHPにはグラフを描画するライブラリがあまりない
一番最初に気になったのは、Canvasで描画したグラフと同等のものをサーバープログラムであるPHPで描画できるのか?でした。
制作工程として、設計→デザイン→コーディング→システムとなるのですが、デザインがすでにあがっており、お客様にもOKをもらっていました。
つまり、デザイン通りのグラフを描画し、バックエンドで出力するPDFにも同様のグラフが必要になります。
PHPのグラフライブラリといえば、pChartやJp Graph等がありますが、JavascriptでCanvasに描画するほどデザインに齟齬が無いように描画できず、使い方を調べたり、実際にプログラムを書いたりする時間を考えると納期的にあまり現実的ではありませんでした。
Javascriptで描画したCanvasを画像として出力
前項のこともあり、PHPのライブラリでデザイン通りのグラフ描画を諦め、JavascriptでCanvasに描画したものを画像化して、それをPHPでPDF化できないか調べたところありました!
<code>
//canvasの要素を変数化
var canvas = document.getElementById('canvas');
//描画内容をデータURIに変換する
var binary = canvas.toDataURL('image/png');
</code>
このコードでid="canvas"のグラフを描画したCanvasをデータbinaryに変換できました。
このbinaryデータをajax等でサーバープログラムに送信し、PHPで受け取ってGD(画像処理ライブラリ)で処理することにより、Canvasの内容をまるっと画像化できました。
PHPの画像処理ライブラリGD
GDは画像を生成するためのPHPライブラリです。
今回利用したのは、前項で送信されたCanvasのバイナリデータをPHPで受け取り、GDで画像としてサーバー内に書き出しました。
下記は、受け取ってからGDで画像として書き出したコードです。
<code>
//Base64エンコードされているバイナリデータをデコード
$img_data = base64_decode($img_data);
//文字列の中のイメージストリームから新規イメージを作成する
$img_res = imagecreatefromstring($img_data);
//PNG画像を保存する際に、完全なアルファチャネル情報を保存するかどうかを指定する
imagesavealpha($img_res, true);
//PNGイメージをファイルに出力する
imagepng($img_res, 画像出力場所とファイル名);
</code>
PHPのPDF作成ライブラリ「mPDF」
残すところは、HTMLをPDF化する処理です。
PDF化するライブラリも色々あるのですが、日本語に対応していること、HTMLをサポートしていることからこちらのライブラリを使用しました。
HTMLデータをある程度そのまま使用し、HTML上の<canvas>タグのところを<img alt="" src="null" />タグに置き換え(前項で出力した画像)ましたが、ここで問題が発生します。
HTMLをそのまま使えるライブラリなのですが、モダンコーディングやCSSに対応しておらず一部を置き換えたり削除したり追加したりと調整に結構手間取りました。
PDF出力用テンプレートとして作ったHTMLをブラウザ上で見たときの表示と、PDF化した時の表示が異なり、何度PDFを出力したことか…。
多少の妥協が必要になった部分もあることを明記しておきます。
まとめ
今回Canvasを画像化できるようになり、画像合成するようなページで実際合成された画像をログとして画像を出力したり、Canvasの描画だけで留まらずその後も色々な事に使えるといった有用性が出来ました。
例えば、画像合成をおこなうようなキャンペーンページで、どの素材を何人の方が選択したといったレポートをもらうことがあると思います。
ジーピーオンラインではさらにユーザーが実際に合成した画像を見たいという要望をかなえられます!!
WRITERナカオ システムエンジニア
携帯電話販売代理店業界で某キャリアショップにて店長を経験したのち、ヒョンな事から気づけばWEBエンジニアな事をしており、2015年にジーピーオンライン入社。元店頭販売員なのでコミュ力高めです。案件毎に何か新しい事や便利になるような事ができないか画策中。数年前から海釣りにハマっており、どうやったらどんな魚種が釣れるのか日々勉強中。