Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not rendering shadow dom elements #430

Closed
fernandezpaco opened this issue Aug 25, 2014 · 20 comments · Fixed by #2581
Closed

Not rendering shadow dom elements #430

fernandezpaco opened this issue Aug 25, 2014 · 20 comments · Fixed by #2581
Labels

Comments

@fernandezpaco
Copy link

I am working on a new project using polymer webcomponents.

The problem is that html2canvas is not rendering the shadow dom

Can you please tell me where should i work on your library in order to have support for webcomponents?

@niklasvh
Copy link
Owner

You'd probably need to look into the node parser (https://github.com/niklasvh/html2canvas/blob/master/src/nodeparser.js) and check whether a node has a shadow DOM before queueing to render it.

@fernandezpaco
Copy link
Author

Here?

negativeZindex.concat(nonInlineNonPositionedDescendants).concat(nonPositionedFloats)
.concat(inFlow).concat(stackLevel0).concat(text).concat(positiveZindex).forEach(function(container) {
this.renderQueue.push(container);
if (isStackingContext(container)) {
this.parse(container);
this.renderQueue.push(new ClearTransform());
}
}, this);

Can you give me a hint about next step? :)

@niklasvh
Copy link
Owner

You'll need to to correctly order the nodes there for rendering (for more information see http://www.w3.org/TR/CSS21/visuren.html#z-index), but prior to that you'll need to fetch the shadow dom nodes for each context stack.

@niklasvh niklasvh changed the title Not rendeting shadow dom elements Not rendering shadow dom elements Nov 8, 2014
@jordanaustin
Copy link

@fernandezpaco have you looked into this any further? I'm pretty interested in this feature as well.

@rcocetta
Copy link

rcocetta commented Apr 7, 2016

@niklasvh Did somebody fix this issue? I'd be interested in using the library, but I'm using Polymer and ShadowDOM and it's not working for me.

@rahulkris123
Copy link

var node = parentContainer.node; if(node.shadowRoot !== null){parentContainer.node = node.shadowRoot.querySelector('div');

The above lines in NodeParser.prototype.getChildren did render shadowDOM elements

@niklasvh can you confirm if this is right approach?

@mkhatib
Copy link

mkhatib commented May 9, 2017

Unfortunately this also fails because of the way html2canvas tag the node to be rendered and then clone the entire document and inability to pierce shadow-dom using querySelector.

Even when tagging the node up to the document root the tagging seems to be lost after the first shadow dom during the cloning. Not sure what's happening there.

@srajabhoj
Copy link

@niklasvh can you share a link (https://github.com/niklasvh/html2canvas/blob/master/src/nodeparser.js) again, it shows 404.

@tmatetwar
Copy link

@niklasvh : We are facing the same issue (unable to render SHADOW-DOM), let us know if anyone had worked on it.

@val1984
Copy link
Contributor

val1984 commented Feb 28, 2018

@srajabhoj Following version 1.0.0 rewrite, it's probably https://github.com/niklasvh/html2canvas/blob/master/src/NodeParser.js

@srajabhoj
Copy link

hey anyone got solution for this, also I am facing to capture images div which have scroll, please suggest way, any lead will be helpful

@Jeffen
Copy link

Jeffen commented Jan 30, 2019

My workaround is to clone the content and css that as you want to render a HTMLElement , then append it to document.body. Set style filter:opacity(0) because html2canvas does not support this but supported in modern browser. Remove it after render.

However, it is very hard to do if you included many shadow-dom element in the content you want to render. Still have no idea on that.

Here is my code in Angular

const newRef = this.renderRef.nativeElement.cloneNode(true);
this.renderer.setStyle(newRef, 'filter', 'opacity(0)');
this.renderer.appendChild(document.body, newRef);
html2canvas(newRef).then(canvas => {
     if (canvas.toBlob) {
          canvas.toBlob(
            blob => {
              fileSaver.saveAs(blob, 'image.jpg');
              this.renderer.removeChild(document.body, newRef);
              alert('Image has been downloaded to your device');
            },
            'image/jpg',
            0.8
          );
     }
});

@rocco
Copy link

rocco commented Mar 28, 2019

@Jeffen this was very helpful, thank you! Also the file saver thing was of great help. Just in case anyone wonders how this works, I did it like this:

$ npm i file-saver

import * as saveAs from 'file-saver';

saveAs(blob, 'image.jpg');

@lf-achyutpkl
Copy link

Is there any update on this issue?
Or any workaround for the app having nested shadow dom?

@trusktr
Copy link

trusktr commented May 17, 2020

The html2canvas lib would need to be updated so that it can traverse the "composed tree" instead of the "light tree".

The "composed tree" (or "flat tree" in other places) is described in the original ShadowDOM draft (click the "collapse" button in the red box to stay on that page instead of re-directing to the new page). Feel free to ask me if you're not familiar with any concept.

If all ShadowRoots have mode:'open', this should be fairly straight forward.

If we want to support ShadowRoots with mode: 'closed', then this will be more complicated and will require patching of attachShadow in order to track references to shadow roots so that we can traverse on them.

Once we know how to traverse the "composed tree" in general, then we'd need to update html2canvas's recursive DocumentCloner.cloneNode method to have it traverse the composed tree instead of the light tree.

@TremayneChrist
Copy link

Slotted content could be trickier to handle. You'd need to find the corresponding slots in order to render the content into the correct place.

<!--my-component-->
<div><slot name="some-region"></slot></div>
<slot></slot>
<!--my-app-->
<my-component>
  Default Slotted Content
  <button slot="some-region">Button</button>
</my-component>

@conceptree
Copy link

Hi, did anyone reached a solution for this shadow dom problem?

@trusktr
Copy link

trusktr commented Mar 24, 2021

I don't think anyone has tried to implement this yet.

Basic steps:

  • Monkey patch Element.prototype.attachShadow so that the lib can have access to all roots, even if they are closed.
  • For each root that is ever created with attachShadow (in the future we would need to consider Declarative Shadow DOM but it may be impossible to track those)
    • Track which roots belong to which nodes (f.e. with a WeakMap).

When traversing later, children of an element with a shadow root will be skipped if an element is seen to have a root (detected with the WeakMap, even a closed one root), and instead traversal will go into the shadow root and into the assignedNodes of any encountered <slot> elements, and continue like so all the way down all shadow roots.

I'm not familiar with the html2canvas impl, but if needed, functions like querySelector could be monkey patched to traverse the composed tree instead of only the local tree of the node on which it is called (make it "piercing").

@trusktr
Copy link

trusktr commented Mar 24, 2021

I went ahead and made Shadow DOM composed tree traversal example, in case it helps someone eventually:

https://codepen.io/trusktr/pen/0d5b3731fcb2ebe54f99316bfb55b117

The output shows the nodes of the composed tree in depth-first preorder (verify by inspecting the elements).

If there are any parts of html2canvas that rely on traversing the DOM tree, it may need to be replaced with something like that.

@nikunjkonduru
Copy link

Hello! Has anybody tried this implementation with slots? I am getting the shadow root, but not the content inside the slot.

https://stackblitz.com/edit/multi-slot-web-component-uwaya7?file=index.html

image

"World" does not show which is in the slot.

Thanks,
Nik

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.