Html2canvas: Html2canvas no synchronous support

Created on 6 Nov 2014  路  6Comments  路  Source: niklasvh/html2canvas

I need html2canvas to run in a loop,

alert("start");
html2canvas(instance.element, {
onrendered: function(canvas) {
alert("inside html2canvas");
// some changes
}
});

alert("finished");

after alert start i get finished alert . html2canvas getting trigger later. i need a synchronous execution. could you help me on this?

Question

Most helpful comment

@niklasvh ,
I am just trying to generate pdf using html2canvas and jspdf

I have a multiple div , each one need to be in separate page of pdf

for that i am trying

var pdf = new jsPDF();
$.each($(arryofdiv),function(){

html2canvas($(this.id), {
onrendered: function(canvas) {
//code
var imgData = canvas.toDataURL("image/jpeg", 1.0);
pdf.addImage(imgData, 'JPEG', 10); // add image to pdf page
});

pdf.addPage();
});
pdf.save("mypdf.pdf");

what issue i am facing is i got pdf before images got inserting in to pdf pages

please help me on this. i got struck here , is there any workaround or any solution which solves this issue

All 6 comments

It works asynchronously, and there isn't and won't be any support for making it synchronous, as it could potentially thread block for several seconds. Resources are downloaded asynchronously and it is unable to proceed before they are ready.

If you use ES6, you can work around it with generators, but I don't see why you would want to freeze the browser.

@niklasvh ,
I am just trying to generate pdf using html2canvas and jspdf

I have a multiple div , each one need to be in separate page of pdf

for that i am trying

var pdf = new jsPDF();
$.each($(arryofdiv),function(){

html2canvas($(this.id), {
onrendered: function(canvas) {
//code
var imgData = canvas.toDataURL("image/jpeg", 1.0);
pdf.addImage(imgData, 'JPEG', 10); // add image to pdf page
});

pdf.addPage();
});
pdf.save("mypdf.pdf");

what issue i am facing is i got pdf before images got inserting in to pdf pages

please help me on this. i got struck here , is there any workaround or any solution which solves this issue

@athavan13 you need to wait for all the html2canvas renderings are done and then render your pdf, i suggest you to check promises

http://api.jquery.com/category/deferred-object/

https://www.promisejs.org/

http://documentup.com/kriskowal/q/

I had same scenario, where I had to zip multiple images..
Solution is like mentioned by @pardo .
One way to achieve this by using JQuery and array of promises, actual code would look like this:

var deferreds = [];
for (let i = 0; i < arryofdiv.length; i++) {
    var deferred = $.Deferred();
    deferreds.push(deferred.promise());
    generateCanvas(i, deferred);
}

$.when.apply($, deferreds).then(function () {
  // final pdf save step
});
function generateCanvas(i, deferred){
  html2canvas(document.querySelector("#div-" + i)).then(canvas => {
    //  pdf add image code   
  });
}

You can also implement it with each and passing the object.
posting solution here in case someone needs it in future or anyone can suggest a better way of doing this.

I had a task to export 9 charts which was displayed in 9 separate division,
To export all charts i used html2canvas function, i wanted to export each graph in each pdf sheets with a4 size
below is my logic to extract all 9 charts on one click,
I am using angular 2(now 6) framework.

  • On click i ll execute generateAllPdf() function,
  • I ll gather all 9 id's from my html collection,
  • iterate through each id and call html2canvas function,
  • as html2canvas runs in background to process images, i m using
    await on function,
  • after the html2canvas completes its process, i ll save the
    document,
  • If suppose i wont use await i ll end-up in downloading an empty
    page.

below is my code logic,

// As All Functions in js are asynchronus, to use await i am using async here
 async generateAllPdf() {
    const doc = new jsPDF('p', 'mm', 'a4');
    const options = {
      pagesplit: true
    };
    const ids = document.querySelectorAll('[id]');
    const length = ids.length;
    for (let i = 0; i < length; i++) {
      const chart = document.getElementById(ids[i].id);
      // excute this function then exit loop
      await html2canvas(chart, { scale: 1 }).then(function (canvas) { 
        doc.addImage(canvas.toDataURL('image/png'), 'JPEG', 10, 50, 200, 150);
        if (i < (length - 1)) {
          doc.addPage();
        }
      });
    }
    // download the pdf with all charts
    doc.save('All_charts_' + Date.now() + '.pdf');
  }

I had a task to export 9 charts which was displayed in 9 separate division,
To export all charts i used html2canvas function, i wanted to export each graph in each pdf sheets with a4 size
below is my logic to extract all 9 charts on one click,
I am using angular 2(now 6) framework.

  • On click i ll execute generateAllPdf() function,
  • I ll gather all 9 id's from my html collection,
  • iterate through each id and call html2canvas function,
  • as html2canvas runs in background to process images, i m using
    await on function,
  • after the html2canvas completes its process, i ll save the
    document,
  • If suppose i wont use await i ll end-up in downloading an empty
    page.

below is my code logic,

// As All Functions in js are asynchronus, to use await i am using async here
 async generateAllPdf() {
    const doc = new jsPDF('p', 'mm', 'a4');
    const options = {
      pagesplit: true
    };
    const ids = document.querySelectorAll('[id]');
    const length = ids.length;
    for (let i = 0; i < length; i++) {
      const chart = document.getElementById(ids[i].id);
      // excute this function then exit loop
      await html2canvas(chart, { scale: 1 }).then(function (canvas) { 
        doc.addImage(canvas.toDataURL('image/png'), 'JPEG', 10, 50, 200, 150);
        if (i < (length - 1)) {
          doc.addPage();
        }
      });
    }
    // download the pdf with all charts
    doc.save('All_charts_' + Date.now() + '.pdf');
  }

I tried with your logic ..after executing first loop (image) it throws error as Error: Supplied Data is not a valid base64-String jsPDF.convertStringToImageData . can you suggest more

Was this page helpful?
0 / 5 - 0 ratings