I'm trying to download PDF with SVG content using jsPDF library, it is able to download the file, but there is no content inside it, it is empty PDF.
This is my code:
const downloadPDF = (goJSDiagram) => {
const svg = goJSDiagram.makeSvg({scale: 1, background: "white"});
const svgStr = new XMLSerializer().serializeToString(svg);
const pdfDoc = new jsPDF();
pdfDoc.addSvgAsImage(svgStr, 0, 0, pdfDoc.internal.pageSize.width, pdfDoc.internal.pageSize.height)
pdfDoc.save(props.model[0].cName?.split(" (")[0] + ".pdf");
}
When I do console.log(svgStr), I can see the SVG XML string. What changes should I make to render the content inside PDF?
I think I know what is going on after getting a good hint from this Github issue:
There's the issue that addSvgAsImage() is asynchronous
You are not awaiting the call to finish before calling save! That means you are trying to save before the SVG has started rendering to the PDF.
See the quite simple code in question:
jsPDFAPI.addSvgAsImage = function(
// ... bla bla
return loadCanvg()
.then(
function(canvg) {
return canvg.fromString(ctx, svg, options);
},
function() {
return Promise.reject(new Error("Could not load canvg."));
}
)
.then(function(instance) {
return instance.render(options);
})
.then(function() {
doc.addImage(
canvas.toDataURL("image/jpeg", 1.0),
x,
y,
w,
h,
compression,
rotation
);
});
As you see, it is just a chain of Thenables. So you simply need to await the Promise, which means your code would look something like this in ES2015+:
const downloadPDF = async (goJSDiagram) => {
const svg = goJSDiagram.makeSvg({scale: 1, background: "white"});
const svgStr = new XMLSerializer().serializeToString(svg);
const pdfDoc = new jsPDF();
await pdfDoc.addSvgAsImage(svgStr, 0, 0, pdfDoc.internal.pageSize.width, pdfDoc.internal.pageSize.height)
pdfDoc.save(props.model[0].cName?.split(" (")[0] + ".pdf");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With