
本文详解在 mPDF 中通过 WriteText() 实现文本水平居中的局限性,并推荐更可靠、可控的替代方案(如 WriteCell()、MultiCell() 或 HTML/CSS 渲染),附完整可运行示例与关键注意事项。
本文详解在 mpdf 中通过 `writetext()` 实现文本水平居中的局限性,并推荐更可靠、可控的替代方案(如 `writecell()`、`multicell()` 或 html/css 渲染),附完整可运行示例与关键注意事项。
WriteText() 是 mPDF 中一个底层坐标驱动的文本绘制方法,其签名 WriteText($x, $y, $text) 仅接受绝对像素坐标(左上角起点),不支持原生对齐参数。这意味着它始终以左对齐方式将文本“锚定”在指定坐标点,无法直接实现居中——你看到的“L-to-R”效果实为默认行为,而非可配置选项。
❌ 不推荐:硬调 WriteText() 的 X 坐标(误差大、难维护)
虽然理论上可通过估算文本宽度和容器宽度来手动计算居中 X 坐标:
$width = $pdf->GetStringWidth("This is a text"); // 获取文本像素宽度
$centerX = ($pdf->w - $width) / 2; // 假设居中于页面宽度
$pdf->WriteText($centerX, 20, "This is a text");
但该方式存在严重缺陷:
- GetStringWidth() 受字体、字号、字间距影响,精度有限;
- 页面边距(leftMargin, rightMargin)未被自动扣除;
- 多行文本、换行、缩放等场景完全失效;
- 代码可读性差,后期难以维护。
✅ 推荐方案:使用支持对齐的高级方法
方案一:WriteCell() —— 精确控制单行文本对齐
WriteCell() 允许指定宽高区域及对齐方式('L'/'C'/'R'),是替代 WriteText() 的最佳选择:
$pdf = new \Mpdf\Mpdf();
$pdf->AddPage();
$pdf->setSourceFile('PDF/Sample.pdf');
// 在 (20, 20) 位置绘制一个 150px 宽 × 20px 高的单元格,文本居中
$pdf->WriteCell(150, 20, "This is a text", 0, 1, 'C', false, '', 0, true);
// 参数说明:宽, 高, 文本, 边框, 换行, 对齐('C'=居中), 背景, 链接, 伸缩, 自动换行
方案二:MultiCell() —— 支持多行+自动换行+居中
适用于长文本或需自动折行的场景,同样支持 'C' 对齐:
$pdf->MultiCell(150, 10, "This is a longer text that may wrap across multiple lines.", 0, 'C', false); // 参数说明:宽, 行高, 文本, 边框, 对齐, 背景填充
方案三:HTML/CSS 渲染(最灵活、语义清晰)
mPDF 原生支持 HTML 解析,利用 CSS text-align 实现声明式居中:
$html = '<div style="text-align: center; margin-top: 20px;">This is a text</div>'; $pdf->WriteHTML($html);
优势:兼容响应式布局、字体样式、颜色、甚至内联 ;适合复杂排版需求。
⚠️ 注意事项
- 弃用旧版加载方式:你代码中混用了 FPDI 和 FPDF 的手动 autoload,易引发类冲突。现代 mPDF(v8.0+)已内置 PDF 操作能力,无需额外引入 FPDI 或 FPDF(除非需合并外部 PDF)。若确需合并,请统一使用 setasign/fpdi + mpdf/mpdf 组合,并通过 $pdf->importPage() 替代 setSourceFile()。
- 坐标系差异:mPDF 默认原点在左上角(0,0),Y 轴向下增长;WriteCell() 的 Y 坐标由前一单元格自动递进,避免手动计算。
- 字体与编码:中文居中需确保已注册支持 UTF-8 的字体(如 dejavusans),并在构造时启用:new \Mpdf\Mpdf(['autoScriptToLang' => true, 'autoLangToFont' => true])。
综上,放弃对 WriteText() 的对齐幻想,拥抱 WriteCell()、MultiCell() 或 HTML 渲染——它们不仅语法简洁、语义明确,更能保障跨版本兼容性与长期可维护性。











