Перейти к содержимому
getnextpdf.com

Изображения, таблицы и списки

Один только текст редко даёт законченный документ. В этом руководстве вы добавите три повседневных строительных блока: изображение, таблицу и маркированный список. Вы напишете два небольших сценария, и каждый из них создаст настоящий файл PDF (Portable Document Format), который можно открыть сразу же.

  • 01-image.php — одностраничный PDF с заголовком и янтарным квадратным изображением, размещённым в точной позиции на странице.
  • 02-table-and-lists.php — одностраничный PDF с небольшой таблицей книг и маркированным списком под ней.

Оба сценария — это законченные программы. Продолжайте использовать папку проекта из первого руководства и сохраняйте каждый сценарий рядом с composer.json.

Этот сценарий содержит собственное изображение. Крошечное изображение PNG (Portable Network Graphics) размером 8 x 8 пикселей хранится внутри сценария в виде строки 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, и вы найдёте заголовок, одну строку текста и янтарный квадрат.

  • Сначала сценарий декодирует строку Base64 обратно в байты изображения и записывает их в out/amber-square.png. Это лишь приём для автономного руководства. Урок начинается с вызова image(), который точно так же читает любой существующий файл PNG или JPEG (Joint Photographic Experts Group).
  • @mkdir(__DIR__ . '/out') создаёт папку для вывода. Знак @ скрывает безобидное предупреждение, которое вы получили бы, если бы папка уже существовала, так что сценарий можно запустить два раза подряд.
  • image() принимает путь к файлу, а также позицию и размер печати. Позиции и размеры измеряются в пунктах, и 72 пункта равны одному дюйму. Начало координат страницы — левый верхний угол, поэтому y: 160 означает 160 пунктов вниз от верхнего края.
  • Пиксели и пункты — это разные вещи. В изображении всего 8 x 8 пикселей, но width: 96, height: 96 печатает его как квадрат шириной в одну и одну треть дюйма. Размер печати выбираете вы; количество пикселей его не определяет.
  • image() размещает изображение точно в указанном вами месте. Этот вызов не сдвигает позицию письма, которую использует cell(). Если сначала написать текст, а затем разместить изображения, они не столкнутся друг с другом.
  • NextPDF читает изображение только из локального файла, никогда из веб-адреса. Перед встраиванием он проверяет, что файл является настоящим, поддерживаемым изображением. Эта защита оберегает вас, когда имена файлов поступают от пользователей.

Шаг 2. Добавьте таблицу и маркированный список

Заголовок раздела «Шаг 2. Добавьте таблицу и маркированный список»

Таблицы и списки — это структурированное содержимое. Самый быстрый способ описать структуру — 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 содержит заголовок, таблицу из трёх столбцов с тёмной строкой заголовка и маркированный список.

  • Сценарий сочетает оба стиля письма на одной странице. cell() печатает крупный заголовок в текущей позиции письма. Затем writeHtml() размещает таблицу и список ниже по странице, под заголовком.
  • ln(8) добавляет небольшой вертикальный отступ высотой в восемь пунктов между заголовком и содержимым HTML. Без него они располагались бы вплотную друг к другу.
  • Таблица использует обычную табличную разметку: <thead> для строки заголовка, <tbody> для строк данных, <th> для ячеек заголовка и <td> для ячеек данных. border="1" рисует линии сетки, а cellpadding="6" добавляет свободное пространство внутри каждой ячейки.
  • Ширины столбцов заданы в процентах, например width: 50%. Они делят полную ширину таблицы, поэтому вёрстка выдерживает изменение размера страницы. Рецепт Вёрстка HTML-таблицы подробно разбирает заголовки, нижние колонтитулы и задание ширины столбцов.
  • Атрибуты style используют объявления CSS (Cascading Style Sheets) — язык оформления веба. Цвета, выравнивание и ширины работают так, как показано здесь. Прежде чем полагаться на другие свойства, сверьтесь с матрицей поддержки CSS.
  • Маркированный список — это просто <ul> с одним <li> на каждый пункт. NextPDF рисует маркеры и отступы за вас.
  • Ошибка с именем ImageProcessingException означает, что файл изображения не удалось прочитать или декодировать. Проверьте путь и убедитесь, что файл имеет поддерживаемый формат, например PNG или JPEG.
  • Ошибка с именем PageLayoutException означает, что позиция или размер были отклонены. Ширина и высота должны быть больше нуля, а путь должен указывать на локальный файл, а не на веб-адрес.
  • Обе ошибки описаны в справочнике по ошибкам движка.
  • Если таблица отрисовывается странно, сначала проверьте разметку. Каждой строке <tr> и ячейке <td> нужен свой закрывающий тег.
  • Во всех остальных случаях начните с руководства по устранению неполадок.

Теперь ваши страницы могут содержать изображения, таблицы и списки. В следующем руководстве вы позволите документу вырасти за пределы одной страницы и сохраните его аккуратным с помощью верхних и нижних колонтитулов и номеров страниц. Для более глубокого погружения в сегодняшние темы рецепт Встраивание изображений в документ охватывает форматы изображений и правила задания размера.