添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一、常规思路

想要将html页面通过pdf文件导出,一般我们使用html2canvas+jsPDDF导出。
单纯使用jsPDF的html()方法要求导入全部字体,于是转换思路,先转成canvas,在通过贴图,贴到pdf中,代码如下:

npm html2canvas
npm jspdf
import html2canvas from 'html2canvas';
import jsPDF from 'jsPDF'; 

具体代码:

// 生成pdf文件流
const elem =document.getElementById('reportContent');
const canvas = await html2canvas(elem!);
//以下是分页
// pdf的尺寸
const pdfWidth = canvas.width;
//a4页面尺寸高比宽为1.414
const pdfHeight = pdfWidth * 1.414;
let pageHeight = canvas.height;
let position: number = 0;
//贴图的宽高
const imgWidth = canvas.width;
const imgHeight = imgWidth / canvas.width * canvas.height;
//将canvas标签转化为base64码
const pageData = canvas.toDataURL('image/jpeg', 2.0);
//创建pdf对象
const pdf = new jsPDF('p', 'pt', [pdfWidth, pdfHeight]);
if(pageHeight < pageHeight) {
    pdf.addImage(pageData, 'JPEG', 0, 0,imgWidth,imgHeight);
} else {
    while(pageHeight > 0) {
        pdf.addImage(pageData, 'JPEG', 0, position,imgWidth,imgHeight);
        position -= pdfHeight ;
        pageHeight -= pdfHeight;
        if(pageHeight > 0) {
            //如果图片还没有贴完,继续添加pdf页
            pdf.addPage();
//如果不需要直接下载,需要pdf的blob文件流,使用output
const pdfBlob = pdf.output('blob');
//直接下载为pdf文件
pdf.save()

参考:https://www.zhangxinxu.com/wordpress/2023/06/js-canvas-jspdf-export-pdf/

但是以上的方案,导出来的pdf页,每页是直接顶满,上下没有页边距,如下图:
在这里插入图片描述

想要添加上下页边距怎么弄呢?

二、通过裁剪canvas贴图

思路:将canvas进行裁剪,每页裁剪的高度,比pdf的页小一点,剩下的留为页边距
上代码:

//创绘制切割后绘制canvas用的canvas标签以及对应的context对象
const perCanvas = document.createElement('canvas');
perCanvas.style.backgroundColor = '#fff'
const context  = perCanvas.getContext('2d');
// 将需要下载的html标签转成canvas标签,并获取对应的base64码
const elem =document.getElementById('reportContent');
const canvas = await html2canvas(elem!);
const canvasData = canvas.toDataURL('image/jpeg', 1.0);
// pdf的尺寸
const pdfWidth = canvas.width;
const pdfHeight = pdfWidth * 1.414;
//切割后的canvas图片的宽高,就等于每页pdf的宽高
perCanvas.width = canvas.width;
perCanvas.height = pdfHeight;
// 每张图片的高度:适当减少100,上下各留50页边距
const perHeight = pdfHeight - 100;
// 计算切割次数
let splitCount = Math.ceil(canvas.height / perHeight);
if(splitCount * perHeight < canvas.height) splitCount++;
//创建img对象,加载完整的canvas图片
const img = new Image();
img.src = canvasData;
//创建pdf对象
const pdf = new jsPDF('p', 'pt', [pdfWidth, pdfHeight]);
//待图片加载完成
await setTimeout(() => {}, 5000)
//切割canvas图片,贴到每一页pdf中
for (let i = 0; i < splitCount; i++) {
    const startY = i * perHeight; // 起始y坐标
    // 清空画布
    context!.clearRect(0, 0, perCanvas.width, pdfHeight);
    context!.fillStyle = '#fff';
    context!.fillRect(0, 0, perCanvas.width, pdfHeight);
    // 绘制当前切割区域的图片
    context!.drawImage(img, 0, startY, perCanvas.width, perHeight, 0, 0, perCanvas.width, perHeight);
    const perCanvasData = perCanvas.toDataURL('image/jpeg', 1.0);
    pdf.addImage( perCanvasData , 'JPEG', 0, 50,perCanvas.width,perCanvas.height);
    if(i < splitCount - 1) pdf.addPage();
pdf.save();

这样导出的每一页pdf都留有上下页边距,如图:
在这里插入图片描述

三、遗留问题

不过这两种方式都存在一个问题:内容截断的问题:
有时候刚好分页裁剪时刚好在一行字的正中间,暂时没有解决办法,有待思考,等找到解决方案再来更新。

jspdf-html2canvas导出pdf 自动根据dom子节点的高度进行分页,避免dom的内容在分页的时候被截断说明直接上代码 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客: 要导出的内容用 .pdf 包裹 ,默认会以.pdf的子节点进行整块的高度计算,如果孙节点需要整块计算,孙节点的父节点上增加.pdf; 如果导出的内容里面有外部图片引用,需要配置外部图片支持跨域; 增加了 图片拖拽 功能,你可
首先引入js <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.0.272/jspdf.debug.js"></script> 其次定义一个点击导出的按钮(我用的时layui,你们可以随便设置,只要是
<script lang="ts"> import { Vue, Component, Prop } from "vue-property-decorator"; import html2Canvas from "html2canvas"; import jsPdf from "jspdf"; @Component({ name.
刚好碰到这么一个需求,前端需要将后端返回的json对象数据生成表单样式的pdf文件,首次接触所以简单记录一下。经过反复查找大致流程为:现在面画一个表单=====>拿到数据将数据放表单中=====>给表单最外层加个ref利用html2Canvas生成base64图片=====>最后用jspdf将图片生成pdf。先上个图: 然后将拿到的数据放入表单(表单大家都会吧,我就不往出贴了,放个图好了,主要看下ref的位置,一些其他的样式问题可根据自身需求调整)中 通过引用并调用html2canvas先生成ba