61

I'm trying to use HTML2Canvas to render the contents of a div. Here is the code:

var htmlSource = $('#potenzial-page')[0];

$('#btn').on("click", function() {          

    html2canvas(htmlSource).then(function(canvas) {
        var img = canvas.toDataURL();
        window.open(img);
    });

});

I'm using v5 beta 3.

When this code runs, it only renders what is visible on the screen. The #potenzial-page div is essentially the entire page, minus the header and footer. All content in this div is visible by scrolling (there are some hidden elements, but I do not want the hidden elements visible in the image.)

I cannot find what's wrong or why it won't save the entire div. I should also note that it appears the image is as tall as the div but only partially visible.

To give an example of what I mean, here is a comparison:

enter image description here

The left is how HTML2Canvas should render the div. The right shows how it renders when it runs the code above. The right image is what's visible in my browsers screen.

I did try adding the height option but it doesn't make a difference.

UPDATE

If I scroll to the very top of the page then run the script it will render the entire div as it should.

How do I render the div without having to scroll to the top?

L84
  • 43,936
  • 58
  • 171
  • 251
  • 5
    I am facing the same issue, how did you solve this? – Rishi Jagati Aug 15 '17 at 12:26
  • Have you seen this solution in SO : "[Html2canvas converting overflowed content to image](https://stackoverflow.com/q/18012044/445600)" A workaround solution is proposed with setting overflow to visible then render then overflow hidden. – Devernay Stéphane Mar 25 '16 at 03:42
  • This probleme is solved : https://github.com/niklasvh/html2canvas/issues/1438#issuecomment-739244530 – zerbene May 07 '21 at 17:36

16 Answers16

54

I hope thet help you

html2canvas(htmlSource, {scrollY: -window.scrollY}).then(function(canvas) {
            var img = canvas.toDataURL();
            window.open(img);
        });
40

A solution that worked for me was to add the following to my css:

.html2canvas-container { width: 3000px !important; height: 3000px !important; }

It prevents html2canvas from limiting the rendering to the viewable area (which seems to be the default).

See here: https://github.com/niklasvh/html2canvas/issues/117

jbgt
  • 1,508
  • 19
  • 21
16

I used window.scrollTo()in my case and it worked for me.

Below is a sample code

$('#btn').on("click", function() { 
    window.scrollTo(0,0);     
    html2canvas(htmlSource).then(function(canvas) {
        var img = canvas.toDataURL();
        window.open(img);
    });
    window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
});
Matthias Schmidt
  • 505
  • 1
  • 6
  • 24
Amit Anand
  • 255
  • 2
  • 6
13

You can add in scroll position as a variable in html2canvas which removes the need to scroll the page.

html2canvas(document.querySelector("#your-element"), { scrollX: 0, scrollY: 0 }).then(function(canvas) {

Kaiser47
  • 176
  • 1
  • 4
  • Perfect. Thank you. – Libin Mar 19 '20 at 13:29
  • 2
    Not working as expected. Earlier it was capturing only the visible part, now it captures from the top (fine), but only some part equal to the height which is visible and rest as blank white. – kb0000 Jun 07 '20 at 08:30
10

I just did something like this and it worked for me:

html2canvas(document.querySelector("#capture2image"), {
            allowTaint: true,
            useCORS: true,
            logging: false,
            height: window.outerHeight + window.innerHeight,
            windowHeight: window.outerHeight + window.innerHeight, 
Ricky Levi
  • 6,168
  • 1
  • 54
  • 58
3

enter image description here

If you have a height set to the div you want to turn to a canvas - you need to remove that before actually taking the snapshot. Otherwise it will just cut it off because of that height.

 $(".yourElemThatHasSomeHeightSet").css("height", "");

Then you will notice that scrolling down - will still cut your document. Simply do a:

$("html, body").scrollTop(0);

before taking the snapshot.

NSP
  • 41
  • 3
3

This is how I've achieved in Reactjs.

Main problem were ratio and scale If you do a quick window.devicePixelRatio, it's default value is 2 which was causing the half image issue.

const printDocument = () => {
  const input = document.getElementById('divToPrint');
  const divHeight = input.clientHeight
  const divWidth = input.clientWidth
  const ratio = divHeight / divWidth;

  html2canvas(input, { scale: '1' }).then((canvas) => {
    const imgData = canvas.toDataURL('image/jpeg');
    const pdfDOC = new jsPDF("l", "mm", "a0"); //  use a4 for smaller page

    const width = pdfDOC.internal.pageSize.getWidth();
    let height = pdfDOC.internal.pageSize.getHeight();
    height = ratio * width;

    pdfDOC.addImage(imgData, 'JPEG', 0, 0, width - 20, height - 10);
    pdfDOC.save('summary.pdf');   //Download the rendered PDF.
  });
}
Mayur Shah
  • 3,184
  • 1
  • 21
  • 40
Priyanshu Chauhan
  • 4,899
  • 3
  • 33
  • 34
1
  window.scrollTo(0,0);  

Add this works for me.

1

for people dont wanna hacky a way for scroll problem.: dom-to-image

  1. you can scroll while you are snapshotting image
  2. and its much more faster (70x according to this blog ).

blog: https://betterprogramming.pub/heres-why-i-m-replacing-html2canvas-with-html-to-image-in-our-react-app-d8da0b85eadf

in the blog it mentions html-to-image. it is fork of dom-2-image. i used dom-to-image (ancestor , original one).

var node = document.getElementById('my-node');

domtoimage.toPng(node)
    .then(function (dataUrl) {
        var img = new Image();
        img.src = dataUrl;
        document.body.appendChild(img);
    })
    .catch(function (error) {
        console.error('oops, something went wrong!', error);
    });
bh_earth0
  • 2,261
  • 21
  • 23
1

The following code worked for me:

      window.scrollTo(0, 0);

      html2canvas(htmlRef, {
        scrollX: -window.scrollX,
        scrollY: -window.scrollY,
        windowWidth: document.documentElement.offsetWidth,
        windowHeight: htmlRef.scrollHeight,
      }).then((canvas) => {
        const img = new Image();

        const imgData = canvas
          .toDataURL("image/png")
          .replace("image/png", "image/octet-stream");

        const pdf = new jsPDF("p", "mm", "a4");
        const imgProps = pdf.getImageProperties(imgData);
        const pdfWidth = pdf.internal.pageSize.getWidth();
        const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
        pdf.addImage(imgData, "JPEG", 0, 0, pdfWidth, pdfHeight);
        pdf.save();
      });
Sai Teja T
  • 142
  • 1
  • 7
0

Another React Approach...

On your submit button on click set the document height dynamically, then call html2canvas using document.body as the first argument

<button onClick={() => {
var body = document.body,
html = document.documentElement;

var height = Math.max(body.scrollHeight, body.offsetHeight,
             html.clientHeight, html.scrollHeight, html.offsetHeight);
             document.body.style.height = `${height}px`

html2canvas(document.body).then(function (canvas) {
                var imgData = canvas.toDataURL('image/pdf')
                var doc = new jsPDF('p', 'mm', [canvas.width, canvas.height])
                doc.addImage(imgData, 'PDF', 10, 10, canvas.width, canvas.height)
                doc.save('name-of-pdf.pdf')
              });
}}>Submit</button>

This will set the html height of public/index.html which html2canvas seems to render from (i.e. not the "root" div).

Paul Sender
  • 144
  • 13
0

This works for me:

  const input = document.getElementById('fragmentForPDF');
  
  // This row fixed problem
  input.parentNode.style.overflow = 'visible';

  html2canvas(input)...
Ruslan Valeev
  • 923
  • 10
  • 18
0
window.scrollTo(0, 0); // this will help to print if div hidden or on mobile screen

html2canvas(document.getElementById("my_div_img")).then(function (canvas) 
                 {
                    //for give white BG
                    var context = canvas.getContext('2d');
                    context.save();
                    context.globalCompositeOperation = 'destination-over';
                    context.fillStyle = "rgb(255, 255, 255)";
                    context.fillRect(0, 0, canvas.width, canvas.height);
                    context.restore();
                    var imgData = canvas.toDataURL('image/jpeg', 1);
                    //console.log(imgData);
}
ajmirani
  • 310
  • 3
  • 7
0

This worked for me:

html2canvas(el, {
    width: el.scrollWidth,
    height: el.scrollHeight,
})

See here for the source.

Aziza Kasenova
  • 1,315
  • 1
  • 7
  • 19
0
<div #potentialContainer id="potentialContainer" class="potentialContainer" style="height: auto;">
some large content here--------------------
</div>

import html2canvas from 'html2canvas';

downloadImage() {

html2canvas(document.querySelector('#potentialContainer'), {
  logging: true,
  allowTaint: false,
  useCORS: true,
  width: document.querySelector('#potentialContainer').scrollWidth,
  height: section.scrollHeight,
  scrollX: -window.scrollX,
  scrollY: -window.scrollY,
}).then((canvas) => {
  var imgWidth = 210;
  var pageHeight = 290;
  var imgHeight = canvas.height * imgWidth / canvas.width;
  var heightLeft = imgHeight;


  var doc = new jsPDF('p', 'mm');
  var position = 0;
  var pageData = canvas.toDataURL('image/jpeg', 1.0);
  var imgData = encodeURIComponent(pageData);
  doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
  doc.setLineWidth(5);
  doc.setDrawColor(255, 255, 255);
  doc.rect(0, 0, 210, 295);
  heightLeft -= pageHeight;

  while (heightLeft >= 0) {
    position = heightLeft - imgHeight;
    doc.addPage();
    doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
    doc.setLineWidth(5);
    doc.setDrawColor(255, 255, 255);
    doc.rect(0, 0, 210, 295);
    heightLeft -= pageHeight;
  }
  doc.save('file.pdf');

 });
 }

Note:- It is important to add style height:auto

The above code will convert a large image to a multipage pdf

Shiju
  • 41
  • 5
0
document.getElementById("dld_report").addEventListener("click", function() {
    // Make sure the area you want to take screenshot is visible in CSS
    document.querySelector('#boundary').style.overflow = 'visible'; 
     
    html2canvas(document.querySelector('#boundary'), {
      // Set the height of screenshot image same as page hieght
      height: window.outerHeight + window.innerHeight,
    }).then(function(canvas) {
        saveAs(canvas.toDataURL(), 'report.png');
    });
});
// dld_report -> button to trigger the screenshot

Set style overflow = "visible" and height were the key to make this happen.

Jaz Pin
  • 117
  • 1
  • 7
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 14 '22 at 07:24