Bỏ qua để đến nội dung
getnextpdf.com

Hình ảnh, bảng và danh sách

Chỉ riêng văn bản thì hiếm khi tạo nên một tài liệu hoàn chỉnh. Trong hướng dẫn này, bạn thêm ba khối xây dựng thường gặp: một bức ảnh, một bảng và một danh sách dấu đầu dòng. Bạn viết hai script nhỏ, và mỗi script tạo ra một tệp PDF (Portable Document Format) thực sự mà bạn có thể mở ngay lập tức.

  • 01-image.php — một PDF một trang với một dòng tiêu đề và một hình vuông màu hổ phách, được đặt ở một vị trí chính xác trên trang.
  • 02-table-and-lists.php — một PDF một trang với một bảng nhỏ về sách và một danh sách dấu đầu dòng bên dưới nó.

Cả hai script đều là những chương trình hoàn chỉnh. Hãy tiếp tục dùng thư mục dự án từ hướng dẫn đầu tiên và lưu mỗi script bên cạnh composer.json.

Script này mang theo bức ảnh của chính nó. Một ảnh PNG (Portable Network Graphics) 8 x 8 pixel bé xíu đi kèm bên trong script dưới dạng một chuỗi Base64. Base64 là một cách biểu diễn dữ liệu nhị phân bằng văn bản thuần, nhờ đó nó có thể nằm trong mã nguồn. Trong một dự án thực tế, bạn sẽ bỏ qua phần đó, vì tệp ảnh của bạn đã tồn tại sẵn trên đĩa.

Lưu tệp này thành 01-image.php và chạy nó bằng 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";

Bạn sẽ thấy Wrote out/image.pdf trên màn hình. Mở out/image.pdf và bạn sẽ tìm thấy dòng tiêu đề, một dòng văn bản và một hình vuông màu hổ phách.

  • Trước tiên script giải mã chuỗi Base64 trở lại thành các byte ảnh và ghi chúng ra out/amber-square.png. Đó chỉ là mẹo để hướng dẫn được khép kín. Bài học bắt đầu ở lời gọi image(), hàm này đọc bất kỳ tệp PNG hoặc JPEG (Joint Photographic Experts Group) hiện có nào theo cùng một cách.
  • @mkdir(__DIR__ . '/out') tạo thư mục đầu ra. Dấu @ ẩn đi cảnh báo vô hại mà bạn sẽ nhận được khi thư mục đã tồn tại, nhờ đó script có thể chạy hai lần liên tiếp.
  • image() nhận vào một đường dẫn tệp cùng với một vị trí và một cỡ in ra. Vị trí và kích thước được đo bằng point, và 72 point bằng một inch. Gốc của trang là góc trên bên trái, nên y: 160 nghĩa là 160 point từ trên xuống.
  • Pixel và point là hai thứ khác nhau. Bức ảnh chỉ có 8 x 8 pixel, nhưng width: 96, height: 96 in nó ra thành một hình vuông rộng một inch và một phần ba. Bạn chọn cỡ in ra; số lượng pixel không quyết định điều đó.
  • image() đặt bức ảnh vào đúng vị trí bạn chỉ định. Nó không di chuyển con trỏ viết mà cell() sử dụng. Viết văn bản trước, rồi mới đặt ảnh, giúp hai thứ không đè lên nhau.
  • NextPDF chỉ đọc ảnh từ một tệp cục bộ, không bao giờ từ một địa chỉ web. Nó kiểm tra tệp là một ảnh thực sự, được hỗ trợ trước khi nhúng nó vào. Lớp bảo vệ đó che chắn cho bạn khi tên tệp đến từ người dùng.

Bước 2: Thêm một bảng và một danh sách dấu đầu dòng

Phần tiêu đề “Bước 2: Thêm một bảng và một danh sách dấu đầu dòng”

Bảng và danh sách là nội dung có cấu trúc. Cách nhanh nhất để mô tả cấu trúc là HTML (Hypertext Markup Language), chính là loại markup mà các trang web sử dụng. NextPDF kết xuất một tập HTML được hỗ trợ thẳng lên trang PDF. Không có trình duyệt nào tham gia.

Lưu tệp này thành 02-table-and-lists.php và chạy nó bằng 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";

Bạn sẽ thấy Wrote out/table-and-lists.pdf. PDF chứa một dòng tiêu đề, một bảng ba cột với một hàng tiêu đề màu tối và một danh sách dấu đầu dòng.

  • Script kết hợp cả hai phong cách viết trên một trang. cell() in dòng tiêu đề lớn tại con trỏ viết hiện tại. writeHtml() sau đó cho bảng và danh sách chảy xuống trang bên dưới nó.
  • ln(8) thêm một khoảng trống dọc nhỏ, cao tám point, giữa dòng tiêu đề và nội dung HTML. Không có nó, hai phần sẽ nằm sát nhau.
  • Bảng dùng markup bảng thông thường: <thead> cho hàng tiêu đề, <tbody> cho các hàng dữ liệu, <th> cho các ô tiêu đề và <td> cho các ô dữ liệu. border="1" vẽ các đường lưới, và cellpadding="6" thêm khoảng thở bên trong mỗi ô.
  • Chiều rộng cột là phần trăm, chẳng hạn width: 50%. Chúng phân chia toàn bộ chiều rộng của bảng, nên bố cục vẫn giữ nguyên khi cỡ trang thay đổi. Công thức Bố trí một bảng HTML đề cập sâu về tiêu đề, chân bảng và việc định cỡ cột.
  • Các thuộc tính style dùng các khai báo CSS (Cascading Style Sheets), ngôn ngữ tạo kiểu của web. Màu sắc, căn chỉnh và chiều rộng đều hoạt động như minh họa ở đây. Trước khi bạn dựa vào các thuộc tính khác, hãy kiểm tra ma trận hỗ trợ CSS.
  • Danh sách dấu đầu dòng chỉ là <ul> với một <li> cho mỗi mục. NextPDF tự vẽ các dấu đầu dòng và phần thụt lề cho bạn.
  • Một lỗi nêu tên ImageProcessingException nghĩa là tệp ảnh không thể đọc hoặc giải mã được. Hãy kiểm tra đường dẫn và đảm bảo tệp thuộc một định dạng được hỗ trợ như PNG hoặc JPEG.
  • Một lỗi nêu tên PageLayoutException nghĩa là một vị trí hoặc kích thước bị từ chối. Chiều rộng và chiều cao phải lớn hơn không, và đường dẫn phải trỏ tới một tệp cục bộ, không phải một địa chỉ web.
  • Cả hai lỗi đều được mô tả trong tài liệu tham chiếu lỗi engine.
  • Nếu bảng kết xuất một cách kỳ lạ, hãy kiểm tra markup trước. Mỗi hàng <tr> và ô <td> đều cần thẻ đóng của nó.
  • Với bất cứ điều gì khác, hãy bắt đầu từ hướng dẫn khắc phục sự cố.

Giờ đây các trang của bạn có thể mang theo ảnh, bảng và danh sách. Trong hướng dẫn tiếp theo bạn cho một tài liệu phát triển vượt quá một trang và giữ nó gọn gàng với đầu trang, chân trang và số trang. Để tìm hiểu sâu hơn về các chủ đề hôm nay, công thức Nhúng hình ảnh vào một tài liệu đề cập đến các định dạng ảnh và các quy tắc định cỡ.