HTML2Canvas does not render full div, only what is visible on screen
Asked Answered
A

18

77

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.

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?

Aruabea answered 25/3, 2016 at 2:48 Comment(2)
Have you seen this solution in SO : "Html2canvas converting overflowed content to image" A workaround solution is proposed with setting overflow to visible then render then overflow hidden.Mapping
This probleme is solved : github.com/niklasvh/html2canvas/issues/…Consciencestricken
T
62

I hope this helps you:

html2canvas(htmlSource, {scrollY: -window.scrollY})
    .then(function(canvas) {
        var img = canvas.toDataURL();
        window.open(img);
    });
Twotone answered 21/1, 2020 at 12:39 Comment(4)
The only answer that worked for me. (My particular case is the map is only partially off-screen and only vertically.)Turaco
Thank you for this! I had a button at the bottom of a page which converts some content way above it to an image. This was the key!Slobbery
Great job. this really helped meAdmissible
It worked but doesn't create new pagesCannice
C
44

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

.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: Render off-screen elements #117

Cathleencathlene answered 8/9, 2017 at 13:26 Comment(0)
A
16

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

Below is 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);
});
Amphiaster answered 14/2, 2019 at 7:40 Comment(2)
This was a great and quick fix for me. In case you don't care about scrolling to the top this works.Tasteless
Thanks for this! Worked greatTiedeman
S
12

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, 
Squaw answered 7/9, 2019 at 11:50 Comment(4)
If you have a scrollable DIV, use height: $('#wrapper')[0].scrollHeight, windowHeight: $('#wrapper')[0].scrollHeight, to get the correct dimensions.Quartered
this is even not taking the full height my container height is 7000 but it is showing data only few of them out of 24 list items I can see only 14Giddy
@JagannathSwarnkar Try to see if the content actually loaded in its entire body before you run the above command, if it's loading only when you scroll etc ... if the data is there - it should take the whole pageSquaw
This worked for me. I wanted to convert html to canvas, and it was not rendering the part which was not on the screen (the part which is only visible when we scroll horizontally). I did the following. html2canvas(document.getElementById("print"), { allowTaint: true, useCORS: true, logging: false, width: window.outerWidth + window.innerWidth, windowWidth: window.outerWidth + window.innerWidth, }).thenJungle
M
11

You can add in the 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) {
Mope answered 25/9, 2019 at 7:43 Comment(2)
Perfect. Thank you.Helluva
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.Pneumothorax
T
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.

Theatricals answered 24/6, 2019 at 12:47 Comment(0)
W
3

This is how I've achieved it in React.

The main problems were ratio and scale. If you do a quick window.devicePixelRatio, its 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.
  });
}
Wachtel answered 31/7, 2020 at 7:19 Comment(0)
P
3

Use:

<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 document.

Photojournalism answered 7/2, 2022 at 10:56 Comment(0)
J
1
  window.scrollTo(0,0);  

Add this works for me.

Jeseniajesh answered 29/8, 2019 at 7:35 Comment(0)
D
1

For people who don't want a hacky way for the scroll problem: dom-to-image

  1. you can scroll while you are snapshotting an image
  2. and it's much faster (70x according to this blog).

Blog: Here’s Why I’m replacing html2canvas With html-to-image in Our React App

In the blog, it mentions html-to-image. It is a 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);
    });
Dignadignified answered 7/5, 2021 at 11:13 Comment(1)
I personally had some problems with a large dom with this lib.Nonie
K
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();
      });
Kilo answered 9/8, 2021 at 5:5 Comment(0)
F
0

Another React approach...

On your submit button, on click, set the document height dynamically, and 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).

Former answered 16/10, 2020 at 15:14 Comment(0)
A
0

This works for me:

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

  html2canvas(input)...
Acting answered 14/11, 2020 at 16:41 Comment(0)
A
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);
}
Adalineadall answered 30/3, 2021 at 7:17 Comment(0)
S
0

This worked for me:

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

See here for the source.

Sarcophagus answered 30/6, 2021 at 5:24 Comment(0)
C
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.

Comfrey answered 14/4, 2022 at 7:11 Comment(1)
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.Sharolynsharon
B
0

FWIW: My biggest issue with this was the difference in rendering on a desktop vs. mobile. html2pdf would render the entire div on the desktop, but only what was visible on the screen on a mobile device. Explicitly setting the height and width of my canvas fixed the issue for me across the board. Because of responsiveness of mobile devices, and wanting continuity, I copy the content of my preview div into a hidden 'print' div and set my styles accordingly in a css file.

      function getPDF() {
         // Create an HTML5 Canvas, write the content of the Flyer div to the canvas, convert it to an image and use jspdf to display it
         $('#FlyerPrintCopy').html($('#FlyerContainer').html());
         var contentDiv = document.getElementById('FlyerPrintCopy');

         //A2 Paper Size (mm): 420 x 594 mm
         /*
          * With 72 DPI and standard margins:
               Adjusted pixel width = (420 / 25.4) * 72 - (2 * 72) ≈ 1075 pixels
               Adjusted pixel height = (594 / 25.4) * 72 - (2 * 72) ≈ 1528 pixels
          */
         var width = 1075;
         // Add 25px to account for the top margin
         var height = 1553;

         $('#FlyerPrintCopy').removeClass('d-none');
         
         // Use html2canvas to render the div content on the canvas
         // Make sure to set the width and height or it will only render the viewable content
         html2canvas(contentDiv, {
            width: width,
            height: height,
            x: 0,
            y: 0
         }).then(function (canvasImage) {
            var img = canvasImage.toDataURL("image/png");

            var doc = new jsPDF({
               unit: 'px',
               format: 'a4'
            });

            var widthScale = width * .375;
            var heightScale = height * .375;
            doc.addImage(img, 'PNG', 20, 25, widthScale, heightScale);
            doc.save('petflyer.pdf');
         });

         $('#FlyerPrintCopy').addClass('d-none');
      }
Breezeway answered 1/8, 2023 at 17:46 Comment(0)
G
0

html2canvas doc said: windowWidth Window.innerWidth Window width to use when rendering Element, which may affect things like Media queries

windowHeight Window.innerHeight Window height to use when rendering Element, which may affect things like Media queries

html2canvas(element , {
        scrollX: -window.scrollX,
        scrollY: -window.scrollY,
        windowWidth: document.documentElement.offsetWidth,
        windowHeight: document.documentElement.offsetHeight
})
Gunnar answered 24/8, 2023 at 7:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.