最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to display an image in two pages in PDF using jsPDF? - Stack Overflow

programmeradmin0浏览0评论

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.

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.

Share Improve this question asked Apr 10, 2014 at 14:31 Manoj NayakManoj Nayak 2,5099 gold badges33 silver badges56 bronze badges 2
  • 2 Any progress on that problem? Have a similar one, and planning cut the image into pieces using canvas, and then put it onto separate pages. – Naz Commented Apr 17, 2014 at 8:21
  • Instead of slice the image after creation,divide ur html into more than one div and convert to images and put one by one.This is what I am doing as an alternate. – Manoj Nayak Commented Apr 18, 2014 at 6:25
Add a comment  | 

8 Answers 8

Reset to default 6
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);
        }
    });

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);
            }

        });
    });

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.

发布评论

评论列表(0)

  1. 暂无评论