Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to save SVG to PDF using jsPDF

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?

like image 393
this.srivastava Avatar asked Oct 20 '25 11:10

this.srivastava


1 Answers

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");
}
like image 146
oligofren Avatar answered Oct 22 '25 23:10

oligofren



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!