Question

I have a html page. In which I have a button , whenerever I click this button it will convert the entire html page into data image using html2canvas and placed it into PDF using jsPDF library. The javascript which I am using is

$("#printButton").click(function(){
html2canvas([document.getElementById('form1')], {
        onrendered: function (canvas) {
            var imageData = canvas.toDataURL('image/jpeg',1.0); 
           var doc = new jsPDF('landscape');
           doc.addImage(imageData,'JPEG',5,20,200,150);
           doc.save('Test.pdf');
     }
    });
});

It is displaying the image in first page only. but whenever the html page size is more, I want to cut the image data and place it in two pages in PDF. Please help me to solve this.

Was it helpful?

Solution 2

This may not be the perfect answer but still works

                $("#btnSaveAsPDF").click(function () {
                html2canvas($("#tblSaveAsPdf_canvas"), {
                onrendered: function (canvas) {
                var imageData = canvas.toDataURL("image/jpeg");
                var image = new Image();
                image = Canvas2Image.convertToJPEG(canvas);
                var doc = new jsPDF();
                doc.addImage(imageData, 'JPEG', 12, 10);
                var croppingYPosition = 1095;
                count = (image.height) / 1095;

                for (var i =1; i < count; i++) {
                        doc.addPage();
                        var sourceX = 0;
                        var sourceY = croppingYPosition;
                        var sourceWidth = image.width;
                        var sourceHeight = 1095;
                        var destWidth = sourceWidth;
                        var destHeight = sourceHeight;
                        var destX = 0;
                        var destY = 0;
                        var canvas1 = document.createElement('canvas');
                        canvas1.setAttribute('height', destHeight);
                        canvas1.setAttribute('width', destWidth);                         
                        var ctx = canvas1.getContext("2d");
                        ctx.drawImage(image, sourceX, 
                                             sourceY,
                                             sourceWidth,
                                             sourceHeight, 
                                             destX, 
                                             destY, 
                                             destWidth, 
                                             destHeight);
                        var image2 = new Image();
                        image2 = Canvas2Image.convertToJPEG(canvas1);
                        image2Data = image2.src;
                        doc.addImage(image2Data, 'JPEG', 12, 10);
                        croppingYPosition += destHeight;              
                    }                  
                var d = new Date().toISOString().slice(0, 19).replace(/-/g, "");
                filename = 'report_' + d + '.pdf';
                doc.save(filename);
            }

        });
    });

OTHER TIPS

html2canvas($('#wrap')[0]).then(canvas => {
        try {
            contentH = $('#wrap').height();
            var img = canvas.toDataURL("image/png", 1.0);
            $w = $actw = canvas.width;
            $h = $acth = canvas.height;
            var pdf = new jsPDF("p", "mm", "a4");
            var width = $maxw = pdf.internal.pageSize.width;
            var height = $maxh = pdf.internal.pageSize.height;
            if (!$maxw) $maxw = width;
            if (!$maxh) $maxh = height;
            if ($w > $maxw) {
                $w = $maxw;
                $h = Math.round($acth / $actw * $maxw);
            }
            pdf.addImage(img, 'JPEG', 0, 0, $w, $h);
            $count = Math.ceil($h) / Math.ceil($maxh);
            $count = Math.ceil($count);
            for (var i = 1; i <= $count; i++) {
                position = - $maxh * i
                alert(position);
                pdf.addPage(img, 'JPEG', 0, 0, $w, $h);
                pdf.addImage(img, 'JPEG', 0, position, $w, $h);
            }
            pdf.save("cart.pdf");
        } catch (e) {
            alert("Error description: " + e.message);
        }
    });

I've updated the code. Now works with multiple pages and more precise cuts without happen black background at the end of the cropped image.

Code

$('#pdf').on('click', function(){

    html2canvas(document.body, {
        onpreloaded: function(){
              $("#barra").hide(); 
        },
        onrendered: function(canvas) {
            $("#page").hide();
            var imgData = canvas.toDataURL('image/jpeg');              
            options = {
                orientation: "0",
                unit: "mm",
                format: "a4"
            };
            var doc = new jsPDF(options, '', '', '');
            doc.addImage(imgData, 'jpeg', 10, 10, 190, 0);
            var corte = 1620; // configura tamanho do corte
            var image = new Image();
            image = Canvas2Image.convertToJPEG(canvas);

            var croppingYPosition = corte;
            var count = (image.height)/corte;


            for (var i =1; i < count; i++) {
                    doc.addPage();
                    var sourceX = 0;
                    var sourceY = croppingYPosition;
                    var sourceWidth = image.width;
                    var sourceHeight = corte;
                    var destWidth = sourceWidth;
                    var destHeight = sourceHeight;
                    var destX = 0;
                    var destY = 0;
                    var canvas1 = canvas;
                    canvas1.setAttribute('height', (image.height)-(corte*i));
                    canvas1.setAttribute('width', destWidth);                         
                    var ctx = canvas1.getContext("2d");
                    ctx.drawImage(image, sourceX, 
                                         sourceY,
                                         sourceWidth,
                                         sourceHeight, 
                                         destX, 
                                         destY, 
                                         destWidth, 
                                         destHeight);
                    var image2 = new Image();
                    image2 = Canvas2Image.convertToJPEG(canvas1);
                    image2Data = image2.src;
                    doc.addImage(image2Data, 'JPEG', 10, 10, 190, 0);
                    croppingYPosition += destHeight;              
                }     


            doc.save('sample-file.pdf');
            $('canvas').remove();
            $('canvas1').remove();
            $("#page").show();
            $("#barra").show();
        }
    });
});

To put a long image on multiple pages I came out with something like this:

var img = new Image();
img.onload = function(){
    while (croppingYPosition < image.height) {
        var sourceX = 0;
        var sourceY = croppingYPosition;
        var sourceWidth = image.width;
        var sourceHeight = maxHeight;
        var leftToCropHeight = image.height - croppingYPosition;
        if (leftToCropHeight < maxHeight) {
            sourceHeight = leftToCropHeight;
        }
        var destWidth = sourceWidth;
        var destHeight = sourceHeight;
        var destX = 0;
        var destY = 0;
        var canvas = document.createElement('canvas');
        canvas.setAttribute('height', destHeight);
        canvas.setAttribute('width', destWidth);
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, 
                        sourceX,
                        sourceY,
                        sourceWidth,
                        sourceHeight,
                        destX,
                        destY,
                        destWidth,
                        destHeight);
        croppedImages.push(CanvasToJPEGConversionService.toJPEG(canvas));
        croppingYPosition += destHeight;
    }
    retur croppedImages;
};
img.src = image.dataURL;

I basically get an array of objects with dataURL (cropped images).

      var pdf = new jsPDF();
      pdf.addImage(image1, 'JPEG', 10, 10);
      pdf.addImage(image2, 'JPEG', 10, 90);
      pdf.addImage(image3, 'JPEG', 10, 170)
      pdf.addPage();
      pdf.addImage(image4, 'JPEG', 10, 10)
      pdf.addImage(image5, 'JPEG', 10, 140)
      pdf.save("download.pdf");

I was facing black page issue but came up with this solution, it works good (short and simple)

html2canvas($("#testId")[0], { allowTaint: true }).then(function (canvas) {
        try {
            var imgData = canvas.toDataURL('image/jpeg');
            let options = {
                orientation: "0",
                unit: "mm",
                format: "a4"
            };
            var doc = new jsPDF(options, '', '', '');
            doc.addImage(imgData, 'jpeg', 0, 0, 210, 0);
            var corte = 1680;
            var image = canvas.toDataURL('image/jpeg');
            var count = (canvas.height) / corte;
            for (var i = 1; i < count; i++) {
                doc.addPage();
                doc.addImage(image, 'JPEG', 0, -330 * i, 210, 0);
            }
            doc.save('sample-file.pdf');
            } catch (e) {
            console.log('error pdf', e);
        }
  

I Came out with this solution hope this will help you:

PDFConverter.prototype.exportToPDF = function (divID, filename, pdfHeight) {

html2canvas($('#' + divID), {                                       //Plugin:html2canvas.min.js,Takes html and convert to canvas.

    onrendered: function (canvas) {
        var doc = new jsPDF();                                    //Plugin:jspdf.min.js Using to export html to pdf file
        var HtmltoPdfPageHeight;
        if (pdfHeight)
            HtmltoPdfPageHeight = pdfHeight;
        var image = new Image();
        image = Canvas2Image.convertToJPEG(canvas);

        var croppingYPosition;
        var count = Math.ceil((image.height) / HtmltoPdfPageHeight);


        for (var i = 1; i <= count; i++) {

            if (i == 1) 
                croppingYPosition = 0;
            else 
                doc.addPage();


            var sourceX = 0;
            var sourceY = croppingYPosition;

            var croppingImageHeight = (image.height - (HtmltoPdfPageHeight * (i-1))) > HtmltoPdfPageHeight ? HtmltoPdfPageHeight : (image.height - (HtmltoPdfPageHeight * (i-1)));
            var destX = 0;
            var destY = 0;
            var croppedCanvas = document.createElement('canvas'); //Canvas using to resize main canvas
            croppedCanvas.setAttribute('height', croppingImageHeight);
            croppedCanvas.setAttribute('width', image.width);
            var ctx = croppedCanvas.getContext("2d");
            ctx.drawImage(image, sourceX,                                //drawImage(img, startX, startY, originalW, originalH, destX, destY, destW, destH);
                                 sourceY,
                                 image.width,
                                 HtmltoPdfPageHeight,
                                 destX,
                                 destY,
                                 image.width,
                                 HtmltoPdfPageHeight);
            var imageToAddatPdf = new Image(); //Final image exporting in pdf page
            imageToAddatPdf = Canvas2Image.convertToJPEG(croppedCanvas);
            doc.addImage(imageToAddatPdf.src, 'JPEG', 10, 10, 185, 0);
            croppingYPosition += HtmltoPdfPageHeight;
        }

        doc.save(filename + '.pdf');



    }
 });
};

Long Image that will fit in multiple pages

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top