Qais Wardag
Qais Wardag

Reputation: 73

Unable to Capture Full Content within an Element and Include It in PDF using html2canvas and jsPDF

I am trying to generate a PDF from the content within a specific div element with the id 'pagebuilder' using html2canvas and jsPDF libraries in my Vue.js project. However, I am facing an issue where the PDF only captures what is visible on the screen, and the content that requires scrolling is not included.

Anyone, who knows how to solve this issue?

Here is the relevant code:

import { jsPDF } from 'jspdf';
import html2canvas from 'html2canvas';


const generatePDF = async function () {
  const doc = new jsPDF();

  // Select the div element with the id 'pagebuilder'
  try {
    const element = document.getElementById('pagebuilder');

    const canvas = await html2canvas(element, {
      useCORS: true,
      allowTaint: true,
      dpi: 200,
      scrollY: -window.scrollY, // Capture full content even if not visible on the screen
    });

    // Get the image data URL
    const imageData = canvas.toDataURL('image/jpeg');

    // Embed the image into the PDF
    doc.addImage(imageData, 'JPEG', 10, 10, 190, 0);
    // Save the PDF
    doc.save('downloaded_file.pdf');
  } catch (error) {
    console.error('Error generating PDF:', error);
  }
};

For testing I also tried to add below options, but it did not work: height: 30000 and windowHeight: 30000

Upvotes: 2

Views: 261

Answers (1)

IT goldman
IT goldman

Reputation: 19485

The htmlcanvas works fine and captures the entire element into a canvas. Only its height consumes more than 1 page in the PDF. That's why it gets cut.

I wanted a nice margin on every page. What I've done is splitting the image to X images then create PDF with X pages. What is the correct height for the partial images? 1600px seems to work but I wonder why is that, with a 297mm sized pages (and 10mm margins).

import { jsPDF } from 'jspdf';
import html2canvas from 'html2canvas';

function splitImageSavePDF(imgData, constantHeight, doc) {
  const image = new Image();
  image.src = imgData;

  image.onload = function() {
    const originalHeight = image.height;
    const originalWidth = image.width;
    const numImages = Math.ceil(originalHeight / constantHeight);

    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");

    for (let i = 0; i < numImages; i++) {
      const top = i * constantHeight;
      const bottom = Math.min((i + 1) * constantHeight, originalHeight);
      const height = bottom - top;

      canvas.width = originalWidth;
      canvas.height = height;

      ctx.clearRect(0, 0, originalWidth, height);
      ctx.drawImage(image, 0, top, originalWidth, height, 0, 0, originalWidth, height);

      const splitDataUri = canvas.toDataURL("image/png");

      doc.addImage(splitDataUri, 'JPEG', 10, 10, 190, 0);
      if (i < numImages - 1) {
        doc.addPage()
      }
    }

    doc.save('downloaded_file.pdf');
  };
}

// usage:

var div = document.querySelector("#test")

html2canvas(div, {
  useCORS: true,
  allowTaint: true
}).then(canvas => {

  const imgData = canvas.toDataURL('image/png');
  const doc = new jsPDF();

  splitImageSavePDF(imgData, 1630, doc)

});

Upvotes: 1

Related Questions