Missing images depending on scale in html2canvas (html2pdf)

Viewed 1323

I am trying to make a PDF of a reasonable amount of text and graphs in my html using html2pdf. So far so good, the PDF gets made and it looks fine. It is about 20 pages. However, multiple graphs are missing. Some relevant information:

  • Most of the missing graphs are at the end of the document. However, the final graph is rendered, so it is not an explicit cut off at the end
  • The text accompanying the graphs is there, but the graph itself is not
  • The missing graphs are all of the same type. Other graphs of this type are rendered and look fine. It does not seem to be a problem with the type
  • If I reduce the scale on the html2canvas configuration to about 0.8, every graph gets rendered (but of course quality is reduced). I'd like the scale to be 2.

The fact that scale influences whether they are rendered or not, gives me the idea that something like timing / timeouts are a problem here. Larger scale means obviously longer rendering time, but it does not seem to wait for it to be done. Or something like that.

Below the majority of the code that makes the PDF. The onClone is necessary for the graphs to be rendered correctly. If it is removed, the problem described above still occurs (but the graphs that áre rendered are ugly).

    const options = {
      filename: 'test.pdf',
      margin: [15, 0, 15, 0],
      image: { type: 'jpeg', quality: 1 }
      html2canvas: {
        scale: 2,
        scrollY: 0,
        onclone: (element) => {
          const svgElements = element.body.querySelectorAll('svg');
          Array.from(svgElements).forEach((item: any) => {
            item.setAttribute('width', item.getBoundingClientRect().width.toString());
            item.setAttribute('height', item.getBoundingClientRect().height.toString());
            item.style.width = null;
            item.style.height = null;
          });
        }
      },
      jsPDF: { orientation: 'portrait', format: 'a4' }
    };

    setTimeout(() => {
      const pdfElement = document.getElementById('contentToConvert');
      html2pdf().from(pdfElement).set(options).save()
        .catch((err) => this.errorHandlerService.handleError(err))
    }, 100);
1 Answers

It sounds like you may be exceeding the maximum canvas size on your browser. This varies by browser (and browser version). Try the demo from here to check out your browser's limit. If you can find 2 browsers with different limits (on my desktop, Safari and Chrome have the same, but the max area in FireFox is a bit lower - iPhone area much lower in Safari), try pushing your scale down on the one with the larger limit until it succeeds, and then see if that fails on the one with the lower limits. There are other limits in your browser (eg. max heap size) which may come into play. If this is the case, I don't have a good solution for you - its usually impractical to get clients to all reconfigure their browsers (and most of these limits are hard anyway). For obvious reasons, browsers don't allow the website to make arbitrary changes to memory limits. If you are using Node.js, you may have more success in dealing with memory limits. Either way (Node or otherwise), it's sometimes better to send things back to the server when you are pushing the limits of the client.

Related