Создание файла PDF из компонентов React
Я создаю приложение для опроса. Люди могут создавать свои опросы и получать данные по вопросам, которые они задают. Я хотел бы добавить функциональность, чтобы пользователи могли загружать результаты в виде PDF.
Например, у меня есть два компонента, которые отвечают за захват вопроса и данных.
<QuestionBox />
<ViewCharts />
Я пытаюсь вывести оба компонента в файл PDF. Затем пользователь может загрузить этот файл PFD. Я нашел несколько пакетов, которые разрешают рендеринг PDF внутри компонента. Однако мне не удалось найти файл, который может генерировать PDF из входного потока, состоящего из виртуального DOM. Если я хочу добиться этого с нуля, какой подход следует придерживаться?
Ответы
Ответ 1
Реакция рендеринга как pdf - это, как правило, боль, но есть способ обойти это, используя canvas.
Идея состоит в том, чтобы конвертировать: HTML → Canvas → PNG (или JPEG) → PDF
Для достижения вышеуказанного вам понадобится:
- html2canvas &
- jsPDF
import React, {Component, PropTypes} from 'react';
// download html2canvas and jsPDF and save the files in app/ext, or somewhere else
// the built versions are directly consumable
// import {html2canvas, jsPDF} from 'app/ext';
export default class Export extends Component {
constructor(props) {
super(props);
}
printDocument() {
const input = document.getElementById('divToPrint');
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF();
pdf.addImage(imgData, 'JPEG', 0, 0);
// pdf.output('dataurlnewwindow');
pdf.save("download.pdf");
})
;
}
render() {
return (<div>
<div className="mb5">
<button onClick={this.printDocument}>Print</button>
</div>
<div id="divToPrint" className="mt4" {...css({
backgroundColor: '#f5f5f5',
width: '210mm',
minHeight: '297mm',
marginLeft: 'auto',
marginRight: 'auto'
})}>
<div>Note: Here the dimensions of div are same as A4</div>
<div>You Can add any component here</div>
</div>
</div>);
}
}
Ответ 2
Вы можете использовать canvans с jsPDF
import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';
_exportPdf = () => {
html2canvas(document.querySelector("#capture")).then(canvas => {
document.body.appendChild(canvas); // if you want see your screenshot in body.
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF();
pdf.addImage(imgData, 'PNG', 0, 0);
pdf.save("download.pdf");
});
}
и вы div с захватом идентификатора:
пример
<div id="capture">
<p>Hello in my life</p>
<span>How can hellp you</span>
</div>
Ответ 3
Это может или не может быть неоптимальным способом выполнения действий, но самое простое решение многостраничной проблемы, которую я обнаружил, состояло в том, чтобы убедиться, что весь рендеринг выполняется перед вызовом метода jsPDFObj.save.
Что касается рендеринга скрытых статей, это решается аналогично исправлению, аналогичному замене текста в изображении CSS, я размещаю абсолютно элемент, который будет отображаться -9999px, слева от страницы, это не влияет на макет и позволяет элементу быть видимым для html2pdf, особенно при использовании вкладок, аккордеонов и других компонентов пользовательского интерфейса, которые зависят от {display: none}
.
Этот метод оборачивает предварительные условия в обещании и вызывает pdf.save()
в методе finally()
. Я не могу быть уверен, что это надежная защита или шаблон, но может показаться, что в большинстве случаев это срабатывает.
// Get List of paged elements.
let elems = document.querySelectorAll('.elemClass');
let pdf = new jsPDF("portrait", "mm", "a4");
// Fix Graphics Output by scaling PDF and html2canvas output to 2
pdf.scaleFactor = 2;
// Create a new promise with the loop body
let addPages = new Promise((resolve,reject)=>{
elems.forEach((elem, idx) => {
// Scaling fix set scale to 2
html2canvas(elem, {scale: "2"})
.then(canvas =>{
if(idx < elems.length - 1){
pdf.addImage(canvas.toDataURL("image/png"), 0, 0, 210, 297);
pdf.addPage();
} else {
pdf.addImage(canvas.toDataURL("image/png"), 0, 0, 210, 297);
console.log("Reached last page, completing");
}
})
setTimeout(resolve, 100, "Timeout adding page #" + idx);
})
addPages.finally(()=>{
console.log("Saving PDF");
pdf.save();
});
Ответ 4
npm install jspdf --save
//код на реакцию
import jsPDF from 'jspdf';
var doc = new jsPDF()
doc.fromHTML("<div>JOmin</div>", 1, 1)
onclick //
doc.save("name.pdf")
Ответ 5
Вы можете использовать ReactDOMServer для рендеринга вашего компонента в HTML, а затем использовать его в jsPDF.
Сначала сделайте импорт:
import React from "react";
import ReactDOMServer from "react-dom/server";
затем:
var doc = new jsPDF();
doc.fromHTML(ReactDOMServer.renderToStaticMarkup(this.render()));
doc.save("myDocument.pdf");
Предпочитаю использовать:
renderToStaticMarkup
вместо:
renderToString
В качестве первого включают HTML-код, который реагирует на.
Ответ 6
Я использовал для печати текущей страницы в формате pdf с использованием js pdf, также я создал демо-версию, для которой вы можете перейти или обратиться к этому [ https://github.com/AkashMishraMS/React-Pdf][1], вы можете получить больше ясности также для Многостраничное создание PDF вы можете рассчитать размер холста и SVG и распечатать. и скоро я создам демо для этого тоже.
[1]: https://github.com/AkashMishraMS/React-Pdf.
Ответ 7
Вы можете использовать ReactPDF
Позволяет легко конвертировать div в PDF.