コンテンツにスキップ
getnextpdf.com

画像、表、リスト

テキストだけで文書が完成することはめったにありません。このチュートリアルでは、日常的に使う 3 つの構成要素、すなわち画像、表、箇条書きリストを追加します。2 つの小さなスクリプトを書き、それぞれがすぐに開ける本物の PDF (Portable Document Format)ファイルを生成します。

  • 01-image.php — 見出しと琥珀色の正方形画像を含む 1 ページの PDF で、画像はページ上の正確な位置に配置されます。
  • 02-table-and-lists.php — 書籍の小さな表と、その下に箇条書きリストを配置した 1 ページの PDF です。

どちらのスクリプトも完結したプログラムです。最初のチュートリアル で使ったプロジェクトフォルダーをそのまま使い、各スクリプトを composer.json の隣に保存してください。

このスクリプトは自身の画像を内部に持っています。ごく小さな 8 x 8 ピクセルの PNG (Portable Network Graphics)画像が、Base64 文字列としてスクリプト内に格納されています。Base64 はバイナリデータをプレーンテキストで表記したものなので、ソースコード内に置くことができます。実際のプロジェクトでは、画像ファイルはすでにディスク上に存在するため、この部分は省略することになります。

これを 01-image.php として保存し、php 01-image.php で実行してください:

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// A tiny 8 x 8 pixel amber PNG, stored as text inside this script.
// In a real project the image file already exists on disk, so you
// would skip this block and point image() at your own file.
$pngBase64 = 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEUlEQVR42mP4Oo8bK2IYWhIAq6BngWh/dt4AAAAASUVORK5CYII=';
@mkdir(__DIR__ . '/out');
$pngPath = __DIR__ . '/out/amber-square.png';
$pngBytes = base64_decode($pngBase64, true);
if ($pngBytes === false) {
fwrite(STDERR, "The embedded image data is damaged.\n");
exit(1);
}
file_put_contents($pngPath, $pngBytes);
$document = Document::createStandalone();
$document->setTitle('Tutorial: images');
$document->addPage();
$document->setFont('helvetica', 'B', 20);
$document->cell(0, 26, 'A picture inside a PDF', newLine: true);
$document->setFont('helvetica', '', 12);
$document->cell(0, 18, 'The amber square below comes from a tiny PNG file.', newLine: true);
// Place the image 72 points (one inch) from the left edge and
// 160 points down from the top, printed as a 96 x 96 point square.
$document->image($pngPath, x: 72, y: 160, width: 96, height: 96);
$document->save(__DIR__ . '/out/image.pdf');
echo "Wrote out/image.pdf\n";

画面に Wrote out/image.pdf と表示されるはずです。out/image.pdf を開くと、見出し、1 行のテキスト、そして琥珀色の正方形が見つかります。

  • スクリプトはまず Base64 文字列をデコードして画像バイト列に戻し、out/amber-square.png に書き出します。これは自己完結型チュートリアルのための工夫にすぎません。本題は image() の呼び出しから始まり、これは既存の PNG または JPEG (Joint Photographic Experts Group)ファイルを同じ方法で読み込みます。
  • @mkdir(__DIR__ . '/out') は出力フォルダーを作成します。@ 記号は、フォルダーがすでに存在するときに発生する無害な警告を隠すので、スクリプトを続けて 2 回実行できます。
  • image() はファイルパスに加えて位置と印刷サイズを受け取ります。位置とサイズはポイント単位で測られ、72 ポイントが 1 インチに相当します。ページの原点は左上隅なので、y: 160 は上から 160 ポイント下がった位置を意味します。
  • ピクセルとポイントは別のものです。画像はわずか 8 x 8 ピクセルですが、width: 96, height: 96 によって、幅 1 と 3 分の 1 インチの正方形として印刷されます。印刷サイズは自分で決めるものであり、ピクセル数が決めるわけではありません。
  • image() は指定した正確な位置に画像を配置します。cell() が使う書き込み位置は移動しません。先にテキストを書き、その後で画像を配置すれば、両者が衝突するのを防げます。
  • NextPDF は画像をローカルファイルからのみ読み込み、Web アドレスからは決して読み込みません。埋め込む前に、そのファイルが実在するサポート対象の画像であることを確認します。このガードは、ファイル名がユーザーから渡される場合の安全策になります。

表とリストは構造化されたコンテンツです。構造を記述する最も手早い方法は、Web ページで使われるものと同じマークアップである HTML (Hypertext Markup Language)です。NextPDF はサポートされている範囲の HTML を、そのまま PDF ページ上にレンダリングします。ブラウザは一切関与しません。

これを 02-table-and-lists.php として保存し、php 02-table-and-lists.php で実行してください:

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
@mkdir(__DIR__ . '/out');
$document = Document::createStandalone();
$document->setTitle('Tutorial: tables and lists');
$document->addPage();
$document->setFont('helvetica', 'B', 20);
$document->cell(0, 26, 'A reading list, two ways', newLine: true);
$document->ln(8);
$html = <<<'HTML'
<h2>The books as a table</h2>
<table border="1" cellpadding="6" style="width: 100%;">
<thead>
<tr style="background-color: #1E3A8A; color: #FFFFFF;">
<th style="width: 50%;">Title</th>
<th style="width: 20%; text-align: center;">Year</th>
<th style="width: 30%; text-align: right;">Pages</th>
</tr>
</thead>
<tbody>
<tr>
<td>The Paper Office</td>
<td style="text-align: center;">2019</td>
<td style="text-align: right;">312</td>
</tr>
<tr style="background-color: #F8FAFC;">
<td>Ink and Pixels</td>
<td style="text-align: center;">2023</td>
<td style="text-align: right;">208</td>
</tr>
</tbody>
</table>
<h2>Why these two books</h2>
<ul>
<li>Short chapters that fit into a lunch break</li>
<li>Worked examples on every page</li>
<li>No jargon without an explanation</li>
</ul>
HTML;
$document->writeHtml($html);
$document->save(__DIR__ . '/out/table-and-lists.pdf');
echo "Wrote out/table-and-lists.pdf\n";

Wrote out/table-and-lists.pdf と表示されるはずです。この PDF には、見出し、濃い色のヘッダー行を持つ 3 列の表、そして箇条書きリストが含まれています。

  • このスクリプトは 1 ページ上で 2 つの書き込みスタイルを併用します。cell() は現在の書き込み位置に大きな見出しを印刷します。続いて writeHtml() が、その下に表とリストをページに沿って流し込みます。
  • ln(8) は見出しと HTML コンテンツの間に、高さ 8 ポイントの小さな垂直の余白を追加します。これがないと、両者は密着してしまいます。
  • 表は通常の表マークアップを使います。ヘッダー行には <thead>、データ行には <tbody>、ヘッダーセルには <th>、データセルには <td> を使います。border="1" は罫線を描画し、cellpadding="6" はすべてのセルの内側にゆとりを加えます。
  • 列幅は width: 50% のようにパーセントで指定します。これらは表の全幅を分割するので、ページサイズが変わってもレイアウトは崩れません。HTML テーブルをレイアウトする レシピでは、ヘッダー、フッター、列サイズの指定を詳しく解説しています。
  • style 属性は、Web のスタイリング言語である CSS (Cascading Style Sheets)の宣言を使います。色、配置、幅はここで示したとおりに機能します。他のプロパティに頼る前に、CSS サポートマトリックス を確認してください。
  • 箇条書きリストは、項目ごとに 1 つの <li> を持つ単なる <ul> です。NextPDF が箇条書きの記号とインデントを描画してくれます。
  • ImageProcessingException という名前のエラーは、画像ファイルを読み込めなかった、またはデコードできなかったことを意味します。パスを確認し、ファイルが PNG や JPEG などのサポート対象の形式であることを確認してください。
  • PageLayoutException という名前のエラーは、位置またはサイズが拒否されたことを意味します。幅と高さは 0 より大きくなければならず、パスは Web アドレスではなくローカルファイルを指し示す必要があります。
  • どちらのエラーも エンジンエラーリファレンス で説明されています。
  • 表の描画がおかしい場合は、まずマークアップを確認してください。すべての <tr> 行と <td> セルには閉じタグが必要です。
  • それ以外の場合は、トラブルシューティングガイド から始めてください。

これで、ページに画像、表、リストを扱えるようになりました。次のチュートリアル では、文書を 1 ページを超えて拡張しつつ、ヘッダー、フッター、ページ番号で整然と保つ方法を学びます。今日扱ったトピックをさらに深く掘り下げるには、文書に画像を埋め込む レシピが画像形式とサイズ指定のルールを解説しています。