Open sporritt opened 4 months ago
..I've put a codepen here demonstrating the difference between setting the src
of an image with a style
attribute on the SVG and without:
and I've discovered from that codepen that in fact it seems to be just the presence of the position:absolute
rule in the style
that causes the issue. So this also works for me to get output:
constructor(context: Context, img: SVGSVGElement) {
super(context, img);
const s = new XMLSerializer();
const bounds = parseBounds(context, img);
img.setAttribute('width', `${bounds.width}px`);
img.setAttribute('height', `${bounds.height}px`);
img.style.position = '';
this.svg = `data:image/svg+xml,${encodeURIComponent(s.serializeToString(img))}`;
this.intrinsicWidth = img.width.baseVal.value;
this.intrinsicHeight = img.height.baseVal.value;
this.context.cache.addImage(this.svg);
}
A couple more bits of information.
JsPlumb adds these SVG elements with position:absolute
and left/top values in their style:
<svg style="position:absolute;left:362px;top:252px" width="834.5" height="104.97673811564006" class="connectorClass jtk-connector"><path d="M 5 0 C 429 40 429 40 833 100 " transform="translate(0,1.5)" pointer-events="visibleStroke" fill="none" stroke="#89bcde" stroke-width="1"></path></svg>
I wondered whether I could remove that position:absolute
and rely on a rule in the stylesheet instead:
.jtk-connector {
position:absolute;
}
this of course works for JsPlumb rendering, but it still doesn't result in output from html2canvas - because the img
element still has position:absolute
set on its style.
I was in a similar situation, The cause of the problem is that SVG tags are drawn asynchronously after HTML rendering. html2canvas duplicates the HTML and changes the duplicated items to a canvas. At this time, the svg tag is not drawn immediately after duplication. So if you want to add svg tags to html canvas you need to duplicate the drawn result and add it to html dynamically. After duplicating, I hid the original and added the duplicate in its place.
Do you have any code you could share to illustrate the process?
Incidentally for anyone else who comes across this issue, we ended up releasing a fork of html2canvas
:
npm install --save @jsplumb/html2canvas
it wasn't my preference but we couldn't get any traction with the library author.
There's a post on our site about this here: https://jsplumbtoolkit.com/blog/2024/05/17/jsplumb-and-html2canvas
Um, sorry I was trying to write a verification code, I think I was wrong about this. I can't attach it because it's my previous company's code, but I think it was a complex problem.
For optimal SVG support try to switch to https://github.com/bubkoo/html-to-image
Bug reports:
Over the years people have reported an issue with the connectors from JsPlumb not appearing in the output from html2canvas but I've never had an opportunity to look at the problem until recently. JsPlumb renders each connection as a single SVG element.
So, if you have this:
and you export it via html2canvas, you get this:
There are no errors reported in the logs. To satisfy myself that this is not simply an issue with the SVG elements created by JsPlumb I rendered a page with an SVG element inside of it and tried to export:
This is what was rendered - the JsPlumb stuff and the stand alone element:
but again no SVG output from htmlcanvas. Tracing the code through I see that SVG elements are processed by the
SVGElementContainer
class:https://github.com/niklasvh/html2canvas/blob/master/src/dom/replaced-elements/svg-element-container.ts
The code is given
img
and usesXMLSerializer
to generate a data URL that will subsequently be loaded into an Image:img
has an extensive set of styles on it and these are serialized into the output (excuse the size of this but thestyle
attribute is the key here):What I have found is that the presence of these
style
attributes in the serialized SVG cause the image to fail to load.If I change the serializer code and blow away all the styles before serializing:
then I get the SVG elements in the output:
I'd be interested to hear your thoughts on this. My feeling is that the
style
attribute in the serialized XML is ignored by the Image class and it's perfectly safe to do this. But I am brand new to this codebase and don't know it at all so maybe there are important considerations I'm overlooking.Specifications: