Manmeet Khurana
Manmeet Khurana

Reputation: 105

How to split page after adding the image using HTML2Canvas and jspdf

Using html2canvas and JsPDF for converting HTML to pdf and using the below code for generating the code this code will give convert the complete HTML of the div to a single image and will show in the pdf as a single page.

import * as jsPDF from 'jspdf';
import html2canvas from 'html2canvas';

    htmltoPDF()
    {
        // parentdiv is the html element which has to be converted to PDF
        html2canvas(document.querySelector("#parentdiv")).then(canvas => {
    
          var pdf = new jsPDF('p', 'pt', [canvas.width, canvas.height]);
    
          var imgData  = canvas.toDataURL("image/jpeg", 1.0);
          pdf.addImage(imgData,0,0,canvas.width, canvas.height);
          pdf.save('converteddoc.pdf');
    
      });

}

For split the code i used below code which split the pages into the multiple pages but not spliting the space correctly because my pdf has small images attached pdf.

var imgWidth = 210;
var pageHeight = 295;
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;

enter code here

var doc = new jsPDF('p', 'mm');
var position = 0;

doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;

while (heightLeft >= 0) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
}
doc.save( 'file.pdf');

Is there any approach to split the page according to the static height which split the image from a particular position?

Upvotes: 4

Views: 11142

Answers (2)

Abhishek
Abhishek

Reputation: 97

  1. First we have to restrict canvas image height and width
html2canvas(divToPrint, {
        width: 2480,
        height: 3508
      }).then((canvas) => {

})
  1. Then we can split this canvas image easily.
// Capture the specified HTML element as a canvas
html2canvas(divToPrint, {
  width: 2480, // Set the width of the canvas
  height: 3508 // Set the height of the canvas
}).then((canvas) => {
  // Define dimensions for the image and PDF pages
  let imgWidth = 400; // Width of the image in the PDF
  let pageHeight = 480; // Height of each PDF page
  let imgHeight = ((canvas.height * imgWidth) / 2454) * 1.24; // Calculate the image height to maintain aspect ratio and apply scaling
  var heightLeft = imgHeight; // Initialize the remaining height to the image height

  // Convert the canvas to a PNG image data URL
  const imgData = canvas.toDataURL("image/png");

  // Create a new jsPDF instance with specified options
  const pdf = new jsPDF({
    orientation: "p", // Portrait orientation
    unit: "mm", // Units in millimeters
    format: [400, 480], // Custom page size
  });

  let position = 0; // Initial position for the image on the PDF page

  // Set the background color for the first page
  pdf.setFillColor(248);
  pdf.rect(0, 0, 400, 480, "F");

  // Add a header image to the first page
  pdf.addImage(Header, "JPEG", 0, 0, 400, 400);

  // Add text to the first page
  pdf.setFontSize(35);
  pdf.text('SMRF 360', 10, 420);
  pdf.setFontSize(15);
  pdf.text('Feedback report', 10, 433);
  pdf.text('March 2021', 10, 440);

  // Add a new page and place the captured image on it
  pdf.addPage();
  pdf.addImage(imgData, "PNG", 0, position, imgWidth, imgHeight);
  heightLeft -= pageHeight; // Decrease the remaining height by the page height

  // Loop to add remaining pages if the content exceeds one page
  while (heightLeft >= 0) {
    position = heightLeft - imgHeight; // Calculate the position for the next image
    pdf.addPage(); // Add a new page
    pdf.addImage(imgData, "PNG", 0, position, imgWidth, imgHeight); // Add the image to the new page
    heightLeft -= pageHeight; // Decrease the remaining height by the page height
  }

  // Save the generated PDF as "Result.pdf"
  pdf.save("Result.pdf");
});

Upvotes: 6

Ved Prakash
Ved Prakash

Reputation: 121

First set doc instance to accept unit as 'pt'. Post this the next step would be to check if image is greater than page size, if so, image will span over multiple pages, as we have docHeight with us, we would be able to get part of the image that would be contained in current page. Now, repeat this for next page (remaining image is say larger again for next page). Code would like below (Here, I wanted image to only occupy 0.8 of page width, height is adjusted accordingly):

  //Read Canvas to be exported
  const appRolesElement = document.getElementById('app-roles-element');
  const appRolesCanvas = await html2canvas(appRolesElement, { onclone: function (document) {
      //Different style requirement for export
      document.querySelectorAll('.right-wrapper').forEach(el => {
        el.style.marginLeft = '0px';
      })
  }});

  const doc = new jsPDF({
    compress: true,
    orientation: 'p',
    unit: 'pt',
    format: 'a4'
  });
  var docWidth = doc.internal.pageSize.getWidth();
  var docHeight = doc.internal.pageSize.getHeight();
  let heightInPlace = 0;
  let appRolesImageDisplayHeight = getDisplayHeight(appRolesCanvas.height, appRolesCanvas.width, docWidth*0.8);
  let appRolesIterationCounter = 0;
  let appRolesSourceClipStartY = 0;

  //Keep checking if a new page is required
  while(appRolesImageDisplayHeight > 0) {
    if(appRolesIterationCounter > 0) {
      doc.addPage();
      heightInPlace = 10;
    }
    ++appRolesIterationCounter;
    const remainingHeightInPage = docHeight - heightInPlace;
    const sourceHeightToBeDisplayed = getSourceHeight(remainingHeightInPage, appRolesCanvas.width, docWidth);
    const clippedImage = await convertURIToImageData(appRolesImage, appRolesCanvas.width, sourceHeightToBeDisplayed, appRolesSourceClipStartY);
    doc.addImage(clippedImage, 'JPEG', 10, heightInPlace, docWidth * 0.8, remainingHeightInPage * 0.8);
    heightInPlace += (remainingHeightInPage * 0.8) + 5;
    appRolesImageDisplayHeight = appRolesImageDisplayHeight - remainingHeightInPage;
    appRolesSourceClipStartY += sourceHeightToBeDisplayed;
  }
  doc.save("export.pdf");


  const getDisplayHeight = (sourceHeight, sourceWidth, displayWidth) => {
    return (displayWidth/sourceWidth)*sourceHeight;
  };

  const getSourceHeight = (displayHeight, sourceWidth, displayWidth) => {
    return displayHeight*(sourceWidth/displayWidth);
  }

Additionally, please use attribute data-html2canvas-ignore for ignoring contents from exports.

Upvotes: 0

Related Questions