niklasvh / html2canvas

Screenshots with JavaScript
https://html2canvas.hertzen.com/
MIT License
30.58k stars 4.81k forks source link

html2canvas: Error finding the DIV in the cloned document #1414

Open ianmh opened 6 years ago

ianmh commented 6 years ago

Bug reports:

Using element.cloneNode(true) or angular.copy(element) on the HTMLElement before passing it to html2canvas returns this error.

html2canvas: Error finding the DIV in the cloned document Uncaught (in promise) Error finding the DIV in the cloned document

Specifications:

Adamkzh commented 6 years ago

Same problem when I try to store the canvas in the local Storage and link to another page by using React.js

<Link to="/system">
            <button className="submitButton"  onClick={this.captureMap} >SUBMIT </button>
</Link>

   captureMap(){
      html2canvas(document.querySelector(".mapboxgl-canvas")).then(canvas => {
        // document.body.appendChild(canvas);
        var image = canvas;
        if(typeof localStorage !== "undefined"){
          localStorage.setItem('mapImg',image.toDataURL());
        }
      });
    }
harishSonar commented 6 years ago

Facing same problem const mainDom = document.createElement('div'); mainDom.appendChild(domElem[0].cloneNode(true)); // domElem is some dom object

When we pass mainDom to html2canvas it shows below error.

html2canvas: Error finding the DIV in the cloned document demo.html#/Demo/Widget:1 Uncaught (in promise) Error finding the DIV in the cloned document

niklasvh commented 6 years ago

@HarishSonar Can you please replicate the issue on jsfiddle?

harishSonar commented 6 years ago

This is fixed now. It seems we cannot work with dom as object in memory, It requires rendering. Adding document.getElementsByTagName('BODY')[0].append(mainDom); solved my problem.

It just that I have to take care of removal of mainDom once html2canvas is processed.

igozali commented 6 years ago

Just for future visitors, I also have the same issue.

I ended up cloning the DOM node, inserting it as the first child of document.body, and using CSS styles position: absolute; top: -16384px; width: ${originalElementWidth}. This is useful if you need to make changes to the DOM node before capturing it as a screenshot.

Also, @niklasvh, here's the jsfiddle if you'd still like to take a look: https://jsfiddle.net/bLwya8sf/1/

DetectiveBox commented 6 years ago

Hi, I met this problem, too. And when I trigger the html2canvas function, all the requests in my project are sent. Could you please tell me you solution? Thanks so much. This is my code: public downBtn(){ var targetDom = document.querySelector('#Box'); var copyDom = targetDom.cloneNode(true); document.body.appendChild(copyDom); html2canvas(copyDom).then( canvas => { var imgData = canvas.toDataURL('image/jpeg'); var img = new Image(); img.src = imgData; img.onload = function () { pdf.addImage(imgData, 'jpeg', 0, 0, this.width 0.225, this.height 0.225); pdf.save('pdf_2.pdf'); }; copyDom.remove(); });

caneta commented 5 years ago

Same issue here: I had to wrap my SVG into a div to avoid this issue...

zhangming8691 commented 5 years ago

Same issue here: I had to wrap my SVG into a div to avoid this issue...

Can talk about how to do it?

zhangming8691 commented 5 years ago

This is fixed now. It seems we cannot work with dom as object in memory, It requires rendering. Adding document.getElementsByTagName('BODY')[0].append(mainDom); solved my problem.

It just that I have to take care of removal of mainDom once html2canvas is processed.

Yes,we must work with rendered element,not work with dom as object in memory

caneta commented 5 years ago

Same issue here: I had to wrap my SVG into a div to avoid this issue...

Can talk about how to do it?

Sure! I've made an example here. It works fine in all browsers except in Internet Explorer 11: the html2canvas approach does not render anything in the final PDF...don't know if its an html2canvas issue or a jsPDF one ...any hints? Thank you

vzkiss commented 5 years ago

This is fixed now. It seems we cannot work with dom as object in memory, It requires rendering. Adding document.getElementsByTagName('BODY')[0].append(mainDom); solved my problem. It just that I have to take care of removal of mainDom once html2canvas is processed.

Yes,we must work with rendered element,not work with dom as object in memory

Why don't you just use the onclone callback? This will let you work with the documentClone before render and make changes to it. For example you have a scrollable table, Gantt chart, and you want to print the full table with the hidden rows visible in a PDF.

html2canvas(document.body, {
        onclone: function(documentClone) {
            // target elements you want to change on the "documentClone" object
        })
        .then(function(canvas) {
            // print canvas with e.g: jsPDF
        });
    };
caneta commented 5 years ago

I've solved for IE11 here.