Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Html2Canvas and jsPDF add 1 image per page

i am using jsPDF and html2canvas (0.4.1) to save images inside a dive to a sinlge pdf.

So far my code works almost ok, but i have one problem.

When the user choose more than one image, images saved in one page. So i want every image in different page. My code is:

<div id="imagesPreview"></div>

<script>
$(document).ready(function(){
$("#modalSave").click(function(){

var inputValue = $('#form29').val()
var imagesnumber = $("#imagesPreview img").length;
//alert(imagesnumber);

var imgData;
html2canvas(document.getElementById("imagesPreview"),{
    useCORS: true,
    onrendered:function(canvas){
    imgData = canvas.toDataURL('image/png');
    //Make The Pdf Document
    var doc = new jsPDF('p','pt','a4');

    if (imagesnumber > 1){
        var i;
        for (i = 1; i < imagesnumber; i++) 
        {
        doc.addImage(imgData,'PNG',10,10)[i];
        doc.addPage()[i];
        }
    }else{
        doc.addImage(imgData,'PNG',10,10);
    }

        if($('#inputValue').val() == ''){
    doc.save('MyPdf.pdf');
    }else{
    doc.save(inputValue+'.pdf');
    }
    window.open(imgData);
    }

    })

});
});
</script>

i am using imagesnumber to count the number of images inside the div.

Any idea please?

like image 438
Yeorgios Laskos Avatar asked Oct 20 '25 09:10

Yeorgios Laskos


1 Answers

You can do it like this:

  1. Loop through all the images
  2. Make a canvas to PNG of each as you go
  3. Add each of these to the PDF as you go
  4. Check to see if the array length has more images to come. If so, addPage()
  5. Add a then() method to make sure it saves the PDF only after everything has been done. Also, in this then() method, check to see where the loop index is at, so that you only save the PDF after the last image has been added.

In my example, those two little blue blocks will be the images that gets added to the PDF. Now, this example won't run on Stack Overflow due to sandbox limitations, but you can see the working JSFiddle here.

const imgs = [...document.querySelectorAll('.img')]
const btn = document.querySelector('a')

btn.addEventListener('click', () => {
    const doc = new jsPDF()
    imgs.forEach((a, i) => {
        html2canvas(a)
        .then(canvas => {
            const img = canvas.toDataURL('image/png')
            doc.addImage(img,'PNG', 45, 45, 100, 100);
            if (imgs.length > (i+1)) {
                doc.addPage()
            }
        })
        .then(() => {
            if ((i+1) === imgs.length) {
                doc.save('MyPdf.pdf')
            }
        })
    })
})
span {width: 20px; height: 20px; background-color: blue; display: inline-block}
a {display: block}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js" integrity="sha384-NaWTHo/8YCBYJ59830LTz/P4aQZK1sS0SneOgAvhsIl3zBu8r9RevNg5lHCHAuQ/" crossorigin="anonymous"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js" crossorigin="anonymous"></script>
<span class="img"></span>
<span class="img"></span>
<a href="#">Download PDF</a>

UPDATE

Here's how to do the same thing with <img> tags, instead of using Html2canvas to create images. In this example you don't need Html2canvas at all. I've updated the above JSFiddle link to show this example.

const imgs = [...document.querySelectorAll('.img')]
const btn = document.querySelector('a')

btn.addEventListener('click', () => {
    const doc = new jsPDF()
    let dataUrl
    async function makeImg(img) {
        let blob = await fetch(img.src).then(res => res.blob());
        dataUrl = await new Promise(resolve => {
            let reader = new FileReader();
            reader.onload = () => resolve(reader.result);
            reader.readAsDataURL(blob);
        })
    }
    imgs.forEach((a, i) => {
        makeImg(a)
        .then(res => {
            doc.addImage(dataUrl, 'PNG', 45, 45, a.style.width, a.style.height)
            if (imgs.length > (i+1)) {
                doc.addPage()
            }
        })
        .then(() => {
            if ((i+1) === imgs.length) {
                doc.save('MyPdf.pdf')
            }
        })
    })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js" integrity="sha384-NaWTHo/8YCBYJ59830LTz/P4aQZK1sS0SneOgAvhsIl3zBu8r9RevNg5lHCHAuQ/" crossorigin="anonymous"></script>
<img class="img" src="https://i.postimg.cc/NfMXcB4c/Screenshot-2020-06-09-at-18-35-56.png">
<img class="img" src="https://i.postimg.cc/NfMXcB4c/Screenshot-2020-06-09-at-18-35-56.png">
<a href="#" style="display: block">Download PDF</a>
like image 122
Ludolfyn Avatar answered Oct 21 '25 22:10

Ludolfyn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!