如何将Fabric Canvas对象导出为PDF?含PHP方案及导出JSON问题求助
Fabric.js Canvas导出JSON及转PDF解决方案
一、先搞定Fabric.js导出JSON的问题
首先得确认你的Fabric Canvas实例是正常初始化的,比如:
const canvas = new fabric.Canvas('你的canvas元素ID');
导出JSON其实很简单,用Fabric自带的方法就行:
// 导出包含所有元素完整信息的JSON const fullJson = JSON.stringify(canvas.toJSON()); // 要是想精简体积,用这个导出无冗余数据的版本 const datalessJson = JSON.stringify(canvas.toDatalessJSON());
要是导出失败,先排查这几个坑:
- 有没有正确创建Canvas实例?别让变量被覆盖或者没初始化就调用方法
- 画布里的图片是不是跨域的?如果是,加载图片时要设置
crossOrigin: 'anonymous',不然会因为安全限制导出失败 - 试试换个稳定版的Fabric.js,比如v5.x,某些旧版本可能有导出bug
二、PHP转PDF的实现流程
拿到JSON后,通过后端转PDF可以这么做:
- 把JSON传给PHP后端
用AJAX提交就行,比如:fetch('/convert-pdf.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: fullJson }); - PHP端解析并生成PDF
推荐用TCPDF或者FPDF,这里拿TCPDF举例子:- 先解析前端传过来的JSON:
$fabricData = json_decode(file_get_contents('php://input'), true); - 初始化PDF实例:
require_once('tcpdf/tcpdf.php'); $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); $pdf->AddPage(); - 遍历Fabric的元素,逐个画到PDF里:
Fabric的JSON里每个元素都有type字段(比如rect、text、image),对应不同的绘制逻辑:foreach ($fabricData['objects'] as $obj) { switch ($obj['type']) { case 'rect': // 绘制矩形 $pdf->Rect($obj['left'], $obj['top'], $obj['width'], $obj['height'], 'F', '', $obj['fill']); break; case 'text': // 绘制文字,注意颜色和字号转换 $pdf->SetFont('dejavusans', '', $obj['fontSize']); $rgb = hexdec(substr($obj['fill'],1,2)).','.hexdec(substr($obj['fill'],3,2)).','.hexdec(substr($obj['fill'],5,2)); $pdf->SetTextColor(...explode(',', $rgb)); $pdf->Text($obj['left'], $obj['top'], $obj['text']); break; case 'image': // 处理图片:把base64转成临时文件再插入 $imgBase64 = str_replace('data:image/png;base64,', '', $obj['src']); $imgContent = base64_decode($imgBase64); $tempPath = tempnam(sys_get_temp_dir(), 'fabric_img'); file_put_contents($tempPath, $imgContent); $pdf->Image($tempPath, $obj['left'], $obj['top'], $obj['width'], $obj['height']); unlink($tempPath); // 用完删掉临时文件 break; // 其他元素类型比如circle、path,照着上面的逻辑扩展就行 } } - 最后输出下载PDF:
$pdf->Output('canvas-export.pdf', 'D');
- 先解析前端传过来的JSON:
三、前端直接转PDF的替代方案
要是不想折腾后端,直接用html2canvas+jsPDF在前端搞定也可以:
// 先装依赖:npm install jspdf html2canvas import jsPDF from 'jspdf'; import html2canvas from 'html2canvas'; // 把Canvas转成图片再生成PDF html2canvas(document.getElementById('你的canvas元素ID')).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); const imgWidth = 210; // A4宽度 const imgHeight = (canvas.height * imgWidth) / canvas.width; let remainingHeight = imgHeight; let yPosition = 0; // 第一页 pdf.addImage(imgData, 'PNG', 0, yPosition, imgWidth, imgHeight); remainingHeight -= 297; // A4高度 // 长图分页处理 while (remainingHeight >= 0) { yPosition = remainingHeight - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, yPosition, imgWidth, imgHeight); remainingHeight -= 297; } pdf.save('canvas-export.pdf'); });
内容的提问来源于stack exchange,提问作者HungryAlmond
相关产品推荐
相关产品推荐

