Links & Annotations
An annotation is a clickable rectangle laid over a page, and Page places one with addUrl() or
addLink() the same way addImage() places an image. Both annotation types share the same border,
radius and dash settings, covered once in Border Appearance rather than twice.
Linking to a URL#
Annotation\Url takes a width, a height and a destination URL, in that order:
use Pop\Pdf\Document;
use Pop\Pdf\Document\Page;
use Pop\Pdf\Document\Page\Annotation\Url;
use Pop\Pdf\Pdf;
$page = new Page(Page::LETTER);
$url = new Url(120, 20, 'https://example.com/report');
$page->addUrl($url, x: 72, y: 700);
Pdf::writeToFile(new Document($page), filename: __DIR__ . '/report.pdf');
addUrl($url, $x, $y) places the rectangle's bottom left corner at $x, $y; both default to 0.
The compiled annotation dictionary carries the URL exactly as passed:
/Type /Annot
/Subtype /Link
/Rect [72 700 192 720]
/Border [0 0 0]
/A <</S /URI /URI (https://example.com/report)>>
setUrl() and getUrl() change and read the destination after construction.
addUrl() returns the page, so a page carries as many URL links as it needs, each added in the same
chain:
use Pop\Pdf\Document\Page;
use Pop\Pdf\Document\Page\Annotation\Url;
$page = new Page(Page::LETTER);
$page->addUrl(new Url(150, 20, 'https://example.com/docs'), x: 72, y: 700)
->addUrl(new Url(150, 20, 'https://example.com/support'), x: 72, y: 660);
Linking Within the Document#
Annotation\Link takes a width, a height and an $xTarget, $yTarget pair — the point on the
destination page the reader lands on:
use Pop\Pdf\Document;
use Pop\Pdf\Document\Page;
use Pop\Pdf\Document\Page\Annotation\Link;
use Pop\Pdf\Pdf;
$page1 = new Page(Page::LETTER);
$page2 = new Page(Page::LETTER);
$link = new Link(120, 20, 100, 400);
$link->setPageTarget(2);
$page1->addLink($link, x: 72, y: 660);
$doc = new Document();
$doc->addPage($page1);
$doc->addPage($page2);
Pdf::writeToFile($doc, filename: __DIR__ . '/linked.pdf');
setPageTarget() takes the destination page's 1-based position in the document — 2 here means the
second page added, regardless of that page's own index. Reading the compiled annotation back confirms
it: the link sits in page one's /Annots array, and its /Dest entry points at page two's own
object, not page one's:
/Dest [5 0 R /XYZ 100 400 0]
Leave setPageTarget() uncalled and the link targets the page it's added to — the same document
without the setPageTarget(2) line points /Dest at page one's own object instead, turning the
link into an in-page jump.
setXTarget() and setYTarget() set the point the destination page scrolls to, matching the
constructor's third and fourth arguments. setZTarget() sets the destination zoom level and
defaults to 0, which under the PDF /XYZ format means "leave the reader's current zoom
unchanged" rather than setting a zoom of zero:
use Pop\Pdf\Document\Page\Annotation\Link;
$link = new Link(120, 20, 100, 400);
$link->setZTarget(1.5);
echo $link->getZTarget(); // 1.5
getXTarget(), getYTarget(), getZTarget() and getPageTarget() read the four values back. A
table of contents page is the usual home for several Link annotations at once, one per entry,
each with its own setPageTarget() pointing further into the document.
Sizing the Clickable Area#
The width and height passed to Annotation\Url or Annotation\Link's constructor set the clickable
rectangle's size, and setWidth() / setHeight() change it afterward — both are inherited from
AbstractAnnotation, so they work identically on either annotation type:
use Pop\Pdf\Document\Page\Annotation\Url;
$url = new Url(120, 20, 'https://example.com/report');
$url->setWidth(200)->setHeight(30);
echo $url->getWidth() . ' x ' . $url->getHeight(); // 200 x 30
The rectangle's origin is the $x, $y passed to addUrl() or addLink(), defaulting to 0;
width and height extend up and to the right from there, so a 120 by 20 annotation added at
72, 700 produces [72, 700, 192, 720] — x, y plus x + width, y + height. There is no default
width or height; both are required constructor arguments.
Border Appearance#
setBorderWidth(), setHRadius(), setVRadius(), setDashLength() and setDashGap() all default
to 0, and a 0 border width draws nothing — an annotation left at its defaults has no visible
outline. Annotation\Link inherits the same five setters, so a link between pages carries a border
exactly as a URL link does:
/Border [6 6 2]
is what setBorderWidth(2)->setHRadius(6)->setVRadius(6) on a Link compiles to — the same
[hRadius vRadius width] shape a Url annotation produces. Setting a width is what makes either
one's rectangle appear:
use Pop\Pdf\Document\Page\Annotation\Url;
$url = new Url(150, 40, 'https://example.com/a');
$url->setBorderWidth(3);
setHRadius() and setVRadius() write a horizontal and vertical corner radius into the same
border definition, but rounding the corners is left to the reader displaying the PDF — a border
rendered by this documentation's toolchain stays square-cornered at any radius, so treat the radii
as data a capable reader can act on rather than a guaranteed visual.
setDashLength() and setDashGap() turn a solid border into a dashed one, and both have to be set
together — setting only one leaves the border solid. Set both, along with a border width, and the
rectangle renders as alternating dashes and gaps:
use Pop\Pdf\Document\Page\Annotation\Url;
$url = new Url(150, 40, 'https://example.com/b');
$url->setBorderWidth(2)->setDashLength(6)->setDashGap(3);
The compiled border definition writes the pair as [dashGap dashLength] — [3 6] for the call
above — so the gap comes first in the emitted array even though setDashLength() is called first in
the chain:
/Border [0 0 2 [3 6]]
getBorderWidth(), getHRadius(), getVRadius(), getDashLength() and getDashGap() read every
value back, in the order you set them rather than the order the compiled array writes them in.
Leaving every border setter at its default is the common case. Reach for setBorderWidth() when
the clickable area has nothing under it and needs its own visible edge.
See Also#
- Pages & Coordinates — the coordinate system
addUrl()andaddLink()both place against - Creating Documents — assembling the pages a
Linkannotation points between - Forms & Fields — the other interactive element a page can carry alongside a link