如何基于FPDF&FPDI实现PDF文档的重复斜向水印?
实现FPDF/FPDI重复斜向水印方案
需求概述
已基于setasign/FPDF和FPDI实现自定义页脚(含请求时间)及单个斜向水印,需将水印改为等间距多行重复显示(可超出页面范围),水印文本为动态生成。
修改思路
要实现重复斜向水印,核心是计算水印文本的尺寸、斜向排列的偏移步长,然后通过循环在页面范围内(及超出部分)批量生成水印:
- 先计算单条水印文本的宽度,确定横向/纵向的重复间距
- 根据水印旋转角度(如45度),计算每次循环时x、y坐标的偏移量
- 设定覆盖范围(从页面外开始到页面外结束),确保整个页面被水印铺满
完整实现代码
替换原有的addWatermark函数,新增批量添加重复水印的函数,并调整页面循环中的调用逻辑:
<?php use setasign\Fpdi\Fpdi; require_once('vendor/autoload.php'); class Watermarked_PDF extends Fpdi { function Footer() { $this->SetY(-10); $this->SetFont('Arial', false, 8); $this->SetTextColor(28, 28, 28); $this->Cell(0, 15, 'File requested on : ' . date('r'), 0, 0, 'C'); } } // 单个旋转水印的底层实现 function addSingleRotatedWatermark($x, $y, $watermarkText, $angle, $pdf) { $angle = $angle * M_PI / 180; $c = cos($angle); $s = sin($angle); $cx = $x * 1; $cy = ($pdf->h - $y) * 1; // 改用PDF自身高度属性,适配不同页面尺寸 $pdf->_out(sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm', $c, $s, -$s, $c, $cx, $cy, -$cx, -$cy)); $pdf->Text($x, $y, $watermarkText); $pdf->_out('Q'); } // 批量添加重复斜向水印 function addRepeatingWatermarks($watermarkText, $angle, $pdf, $spacing = 50) { // 获取当前水印字体的宽度 $textWidth = $pdf->GetStringWidth($watermarkText); // 计算斜向排列时的步长(基于45度调整,可根据角度修改) $stepX = $spacing * cos(deg2rad($angle)) + $textWidth * cos(deg2rad($angle)); $stepY = $spacing * sin(deg2rad($angle)) + $textWidth * sin(deg2rad($angle)); // 计算覆盖范围:从页面外开始,到超出页面足够距离结束 $startX = -$pdf->w; $endX = $pdf->w * 2; $startY = -$pdf->h; $endY = $pdf->h * 2; // 循环生成水印 for ($x = $startX; $x < $endX; $x += $stepX) { for ($y = $startY; $y < $endY; $y += $stepY) { addSingleRotatedWatermark($x, $y, $watermarkText, $angle, $pdf); } } } $pdf = new Watermarked_PDF(); $file_Path = 'documents/'; $file_Name = '13825_2023-07-04'; $pages_count = $pdf->setSourceFile($file_Path . $file_Name . '.pdf'); for ($i = 1; $i <= $pages_count; $i++) { $pdf->AddPage(); $tplIdx = $pdf->importPage($i); $pdf->useTemplate($tplIdx, 0, 0); $pdf->SetFont('Arial', 'B', 15); $pdf->SetTextColor(175, 175, 175); $watermarkText = 'file #' . $file_Name . ' - property of company'; // 调用批量水印函数,间距设为50(可根据需求调整) addRepeatingWatermarks($watermarkText, 45, $pdf, 50); } $pdf->Output();
关键说明
$spacing参数:控制水印之间的间距,数值越小水印越密集,可根据需求调整- 覆盖范围:从页面外开始循环,确保边缘区域也能被水印覆盖
- 适配页面尺寸:改用
$pdf->h获取页面高度,避免固定数值导致的适配问题 - 字体宽度计算:通过
GetStringWidth动态获取文本宽度,保证间距计算准确
内容的提问来源于stack exchange,提问作者jijihbt
相关产品推荐
相关产品推荐

