yWorks / svg2pdf.js

A javascript-only SVG to PDF conversion utility that runs in the browser. Brought to you by yWorks - the diagramming experts
MIT License
649 stars 98 forks source link

svg exporting with cropped dimensions #179

Closed Deep-Codes closed 3 years ago

Deep-Codes commented 3 years ago

My SVG exports in a cropped way in the PDF

Here's the svg

map.txt

Svg is rendered correctly as this:

Screenshot 2021-06-01 at 7 32 37 AM

But on export looks like this:

Screenshot 2021-06-01 at 7 33 13 AM
HackbrettXXX commented 3 years ago

Thanks for reporting this bug. It seems like svg2pdf applies the clip path established by the inner <svg> element wrong. I suspect that the fallback value if no width/height is specified might be wrong here, although I might be wrong:

https://github.com/yWorks/svg2pdf.js/blob/74679131f6045bda56f7ef21640d7c26c4576f18/src/nodes/svg.ts#L122-L125

What happens is: the outer <svg> element establishes a clip rect 600x600 and a viewport transformation because of it's viewBox attribute. The inner <svg> adds another clip rect 600x600. However, this is applied in the scaled coordinate system established by the outer <svg>.

A workaround would probably be to remove the inner <svg> element or replace it by a <g> element.

Deep-Codes commented 3 years ago

@HackbrettXXX Thanks for an extremely fast response

You're Correct replacing it with the <g> tag works.

Screenshot 2021-06-01 at 4 33 38 PM

I am gonna remove the nested <svg> tag from the Layout seems redundant.

So now I can add export to pdf feature in https://www.chloromaps.com/

Would acknowledge this library in the /acknowledgment section.

Thanks a Ton Again! 🎉


There's one issue tho

If i try to download the svg via id

const element = document.getElementById('svg')
doc
  .svg(element, {
  })
  .then(() => {
    // save the created pdf
    doc.save('myPDF.pdf')
  })

it would still give me cropped one , don't if something is wrong from my side

but if I export the SVG using :

const svgDataString = document.getElementById(id).outerHTML;

and put the string in the Online Playground it works 🤔

I have removed the inner tag too

Do you want a MVP of this Issue reproduction ?

Deep-Codes commented 3 years ago

@HackbrettXXX

Here's codesandbox Reprod in react https://codesandbox.io/s/silent-cache-vsldd?file=/src/App.js

If you copy the SVG on paste it in Playground it would correctly give output.

but here it's cropped

yGuy commented 3 years ago

Please strip down the SVG to a small repro and try debugging/bisecting your app against our playground. Please understand that we are only willing to debug large custom code bases in extreme cases - and we're certainly not there. It's great if you report a bug, but please report it properly and don't just drop a complete application for others to debug. Thanks.

Deep-Codes commented 3 years ago

Please strip down the SVG to a small repro and try debugging/bisecting your app against our playground. Please understand that we are only willing to debug large custom code bases in extreme cases - and we're certainly not there. It's great if you report a bug, but please report it properly and don't just drop a complete application for others to debug. Thanks.

Understandable, closing this Thanks ✅

Temp Fix is unsettling the width of SVG Element

zornwal commented 3 years ago

@yGuy I have the same issue, and it is not caused by having a nested SVG element. I use this example which renders correctly in the playground, but when I try to add it to a pdf with height and width like so

let doc = new jsPDF('p','px','a4');
doc.svg(
    item.chart.svgObject, 
    { x: item.layout.pos.x, y: item.layout.pos.y, width: 50, height: 75 })
.then(() => doc.save("hat.pdf"));

it results in the generated pdf being clipped, rather than scaled to size, as seen below. image

As deep code mentions, the svg is rendered perfectly fine in the playground and in my own html, but when added and saved programmatically, it clips the svg instead of scaling it.

I can open a separate issue for this if you want it.

HackbrettXXX commented 3 years ago

@zornwal the issue can probably be resolved by specifying a viewBox attribute on the SVG.

The current behavior of svg2pdf is, that, if the width and height options are specified, they override the width and height attributes on the SVG element. This means if no viewBox attribute is specified, the SVG won't be scaled.

zornwal commented 3 years ago

@HackbrettXXX So I should add a viewBox for the containing SVG then? If I want size (and scale) to be governed by the parameters given with doc.svg(...) what parameters should I give the ViewBox attribute?

Edit: Seems like kludging in a wrapper "<svg viewBox=\"0 0 " + svg.clientWidth + " " + svg.clientHeight + "\">" + svg.innerHTML + "</svg>" resolved the clipping, thanks for the fast reply