我有一个 React 应用程序,页面显示一些包含标题、文本、一些图像等的帖子。我正在尝试从中生成 PDF 文件。
实际页面非常曲折、动态且复杂,因此我没有尝试将 HTML 转换为 PDF,而是使用 jsPDF 包,并从 Redux 存储中插入状态变量作为内容。这将是理想的情况 - 我有生成布局的工具,我有一些内容,但是......我遇到了一个问题。我的帖子的文本长度可以从很小到几页不等,因此在这种情况下,应该将其传递到下一页。我已经弄清楚如何获取“pageHeight”和“textHeight”,因此当“textHeight”大于“pageHeight”时,我可以通过 doc.addPage() 添加另一页,但是文本仅保留在一页上并被切断在页面末尾(请参阅随附的屏幕截图)。这是我到目前为止的代码:
const pdfGenerator = () => {
// Default export is a4 paper, portrait, using millimeters for units
const doc = new jsPDF();
const pageHeight = doc.internal.pageSize.height;
const wrappedText = doc.splitTextToSize(post.text, 200);
doc.setFontSize(14);
const dim = doc.getTextDimensions(wrappedText);
const textHeight = dim.h;
doc.text(15, 10, wrappedText);
if (textHeight >= pageHeight) {
doc.addPage();
}
// const textPages = Math.ceil(dim.h / pageHeight);
// Don't know what to do with it....
doc.save(`${post.title}.pdf`);
};
一种可能的解决方案是将整个文本分割成适合页面的块数组,然后进行循环或通过每次添加 doc.addPage() 来映射它。最大的问题是——它会在随机的地方分割文本,比如在单词的中间。
我尽力寻找解决方案,浪费了很多时间却没有结果......
请帮忙!
const pdfGenerator = () => {
// Default export is a4 paper, portrait, using millimeters for units
const doc = new jsPDF();
const pageHeight = doc.internal.pageSize.height;
const wrappedText = doc.splitTextToSize(post.text, 180);
doc.setFontSize(14);
let iterations = 1; // we need control the iterations of line
const margin = 15; //top and botton margin in mm
const defaultYJump = 5; // default space btw lines
wrappedText.forEach((line) => {
let posY = margin + defaultYJump * iterations++;
if (posY > pageHeight - margin) {
doc.addPage();
iterations = 1;
posY = margin + defaultYJump * iterations++;
}
doc.text(15, posY, line);
});
doc.save(`${post.title}.pdf`);
};
if (format === "PDF") {
const doc = new jsPDF("portrait", "px", "a4");
doc.setFontSize(12);
const pageWidth = doc.internal.pageSize.getWidth();
const pageHeight = doc.internal.pageSize.getHeight();
const xMargin = 25; // left and right margin
const yMargin = 75; // top and botton margin including the header/footer. In px since that's what hte jsPDF is set to use
const lineHeight = doc.getLineHeight(); // default space between lines
const needNewPageAfterThisYPos = pageHeight - yMargin
// the `description` variable here is the pdf content
const wrappedText = doc.splitTextToSize(description, pageWidth - (2 * xMargin)); // account for both the left and right marigns
let yPos;
wrappedText.forEach((line) => {
if (yPos > needNewPageAfterThisYPos) {
doc.addPage();
yPos = undefined;
}
if (yPos === undefined) {
yPos = yMargin;
} else {
yPos = yPos + lineHeight;
}
doc.text(line, xMargin, yPos);
});
this.#addPDFHeaderAndFooter(doc, pageWidth, pageHeight, (yMargin / 2), data.label);
doc.save(file); // file is the file path to save to
} else {
...
}
以及页眉/页脚逻辑
/**
* Private method to add the header and footer to each page of a generated pdf.
*/
#addPDFHeaderAndFooter = (doc, pageWidth, pageHeight, margin, message) => {
const pageCount = doc.internal.getNumberOfPages();
doc.setFont('Times');
doc.setFontSize(10);
for (var i = 1; i <= pageCount; i++) {
doc.setPage(i);
// add the header to the page
doc.text(message, pageWidth / 2, margin, {
align: 'center'
});
// add the footer to the page
doc.text(message, pageWidth / 2, pageHeight - margin, {
align: 'center'
})
}
}