Missing images depending on scale in html2canvas (html2pdf)
Asked Answered
S

1

6

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);
Sheave answered 27/1, 2021 at 11:10 Comment(1)
It seems that scale=2 doesn't leave much room for the graphs to be rendered. Have you checked if a smaller margin on the PDF will have the same effect as a smaller graph scale?Searchlight
G
0

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.

Greenhead answered 7/2, 2021 at 16:14 Comment(2)
Thank you for your response! I had checked the canvas size, that is within the limits. Else I would have expected blank pages (which happens if I make the PDF larger for testing purposes). Heap size might be something to look into, but difficult to solve as you say.Sheave
Well, if it ran out of heap memory, I would expect it to have a blank or truncated document (or no document at all), but clearly it is having trouble with the larger images, so if not canvas, can't think of any other limit offhand. Keep in mind the canvases it is allocating to do its work may be larger than the images it is working with. That's why I suggested testing borderline success/failure scales on different browsers. This might detect a difference whether or not the problem is the canvas size.Greenhead

© 2022 - 2024 — McMap. All rights reserved.