跳到內容

繪製向量圖形 —— 形狀、色彩與線條樣式

本範例會繪製具備填色與描邊的基本圖元:矩形、圓角矩形、圓形、橢圓與線條。每種圖元都可設定填色、描邊色彩與線寬。本範例依循 examples/06-colors-and-drawing.php

每個圖元都對映到 ISO 32000-2 的一個路徑物件。路徑物件是由線段與曲線段組成的形狀,最後以繪圖運算子結束;該運算子會決定形狀要描邊、填色,或兩者皆做。

Terminal window
composer require nextpdf/core:^3

不需要任何選用擴充功能。繪圖與色彩 API 自 1.0.0 起即為穩定版,並可在 8.1–8.4 的 backport 相容矩陣中執行。

先設定繪圖狀態,再進行繪製。 setFillColor()setDrawColor()setLineWidth() 會更新繪圖狀態。後續的 rect()circle()ellipse()roundedRect()line() 會取用該狀態。這些形狀方法都接受樣式引數:'F' 表示填色、'S' 表示描邊(預設值),而 'DF'/'FD' 表示兩者皆做。在內部,填色矩形就是先使用路徑建構運算子 re,再接上填色繪圖運算子。ISO 32000-2 §8.5.3 將 S 指定為描邊、f 指定為填色,並列為主要的路徑繪圖運算子。

色彩採用裝置色彩(device colour)。 setFillColor(r, g, b) 會選用 DeviceRGB。ISO 32000-2 §8.6.4.3 將 rg 定義為 DeviceRGB 的非描邊色彩運算子,並將 g 定義為對應的 DeviceGray 運算子。單一引數形式的 setFillColor($v) 代表灰階值。線寬預設為 1.0,虛線樣式預設為實線(§8.4.3.6)。

此 API 介面由 PHPDoc 自動產生。本範例會用到下列方法:

  • rect(float $x, float $y, float $w, float $h, string $style = 'S'): static
  • roundedRect(float $x, float $y, float $w, float $h, float $r, string $style = 'S'): static
  • circle(float $x, float $y, float $r, string $style = 'S'): static
  • ellipse(float $x, float $y, float $rx, float $ry, string $style = 'S'): static
  • line(float $x1, float $y1, float $x2, float $y2): static
  • setFillColor(int $r, int $g = -1, int $b = -1): static / setDrawColor(...)
  • setLineWidth(float $width): static
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->setFillColor(30, 58, 138);
$doc->rect(20, 30, 60, 40, 'F'); // filled rectangle
$doc->setDrawColor(217, 119, 6);
$doc->setLineWidth(1.0);
$doc->circle(140, 50, 20, 'S'); // stroked circle
$doc->setLineWidth(0.3);
$doc->line(20, 90, 190, 90); // thin rule
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/vector.pdf');

這是完整且可直接在測試載具上執行的範例。它會遵循 NEXTPDF_COOKBOOK_OUTPUT,且不會自行引入任何亂度。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Colors and Drawing');
$doc->addPage();
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, 'Colors and Drawing', newLine: true);
$doc->ln(5);
// --- Filled rectangles: set fill colour, then draw with style 'F' ---
$palette = [
[30, 58, 138], [217, 119, 6], [30, 27, 75],
[239, 66, 35], [21, 128, 61],
];
$x = 15.0;
$rowY = $doc->getY();
foreach ($palette as [$r, $g, $b]) {
$doc->setFillColor($r, $g, $b);
$doc->rect($x, $rowY, 30, 20, 'F');
$x += 35.0;
}
$doc->ln(28);
// --- Outlined shapes: set draw colour + line width, draw with 'S' ---
$doc->setDrawColor(30, 58, 138);
$doc->setLineWidth(0.5);
$y = $doc->getY();
$doc->rect(15, $y, 30, 25, 'S');
$doc->roundedRect(55, $y, 30, 25, 5, 'S');
$doc->circle(110, $y + 12.5, 12.5, 'S');
$doc->ellipse(150, $y + 12.5, 18, 10, 'S');
$doc->ln(33);
// --- Lines at three widths ---
$y = $doc->getY();
$doc->setDrawColor(0);
$doc->setLineWidth(0.2);
$doc->line(15, $y, 195, $y);
$doc->setLineWidth(0.8);
$doc->line(15, $y + 5, 195, $y + 5);
$doc->setLineWidth(1.5);
$doc->line(15, $y + 12, 195, $y + 12);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/vector.pdf';
$doc->save($out);
echo "Created vector.pdf\n";
  • 樣式預設為描邊。 若省略樣式引數,形狀會以描邊方式呈現('S')。看似不可見的形狀,通常是因為未設定描邊色彩,或填上了與頁面背景相同的色彩。傳入 'F' 即可將它填色。
  • 色彩狀態會持續保留。 setFillColor() 會持續生效,直到你變更它為止。在下一個不相關的區塊之前,先重設它(例如 setFillColor(255)),否則該色彩會繼續沿用。
  • 灰階與 RGB 多載的差別。 setFillColor(128) 代表灰階值。setFillColor(128, 0, 0) 則是 RGB。單一引數形式並不是「紅色 128」的意思。
  • 在 API 中 Y 軸是由上往下遞增。 這些繪圖輔助方法以文件左上角作為原點。引擎會替你將其對映到 PDF 以左下角為原點的使用者空間。

每個圖元都只會產生少數幾個內容串流(content stream)運算子。每頁數千個形狀仍可落在 2000 ms / 64 MB 的預算內。處理成本會隨圖元數量線性成長。過程中不會進行點陣化,因此輸出仍維持為向量。

本範例只會繪製你的程式碼指定的幾何圖形。它不會剖析任何輸入,也不會進行任何網路存取。任何來自不可信資料的座標都必須做範圍檢查。範圍檢查可防止惡意值把標記推到頁面範圍之外的遠處。

陳述規範條款參考 ID
路徑物件由線段、矩形與貝茲(Bézier)曲線組成,並以一個繪圖運算子作結。ISO 32000-2§8.5
S 對路徑進行描邊,f 則對路徑進行填色。ISO 32000-2§8.5.3
rg 設定 DeviceRGB 的非描邊色彩;g 設定 DeviceGray。ISO 32000-2§8.6.4.3
虛線樣式的初始值是 [] 0,也就是實線。ISO 32000-2§8.4.3.6

可重現性設定檔 —— 結構性。 向量繪圖本身不帶任何亂度。即便如此,每份儲存的文件都會帶有 trailer /ID 與日期原子(atom)。ISO 32000-2 §8.3.4 也指出,繪圖狀態運算子的確切排列順序沒有語意上的意義,因此正規化器可以重新排列等價的狀態。這裡可以成立的主張,是經過 qpdf 正規化後的結構相等。本範例說明 NextPDF 如何產生這樣的結構;它並未主張全面符合 ISO 32000-2。

不適用。向量繪圖是核心(Core)功能,沒有 Premium 限制。