You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:56:18