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
643 stars 96 forks source link

add method to add SVG from a String and a URL #281

Closed insinfo closed 5 months ago

insinfo commented 6 months ago

add method to add SVG from a String and a URL

yGuy commented 6 months ago

Why?

This lib needs to work on the SVG DOM. Why should it also deal with parsing and loading? What's the use-case?

insinfo commented 6 months ago

my use case is to convert a layout/designer made with fabric.js to PDF in the browser, it would make it much easier if this lib already handles this

image

yGuy commented 6 months ago

Much easier?

Much easier than this: https://stackoverflow.com/a/24109000 ?

HackbrettXXX commented 5 months ago

I'm also against adding this to the library. We could add it as a code snippet to the readme.

mdodge-ecgrow commented 3 weeks ago

I'm trying to add an SVG to a new PDF using this method. Basically when the user clicks a link it is supposed to pop up a modal with the newly created pdf in the modal. I am getting this error: Uncaught (in promise) TypeError: e2.tagName is undefined.

Here is the relevant code in my modal component:

...
const svgLogoData = `<svg xmlns="http://www.w3.org/2000/svg" width="400" height="89.474"><g fill-rule="evenodd"><path fill...</svg>`;
...
const PriceListPdf = (props: PriceListPDFProps) => {
...
useEffect(() => {
        console.log({priceListToExport});
        if (priceListToExport) {
            displayPDF();

        }
    }, [priceListToExport]);

const displayPDF = () => {
        const doc = new jsPDF(
            {
                orientation: 'p',
                unit: 'in',
                format: 'letter',
                putOnlyUsedFonts: true,
                floatPrecision: 16 // or "smart", default is 16
            });

        const left = doc.internal.pageSize.width / 2;
        // const top = doc.internal.pageSize.height / 2;

        const imgWidth = 4;
        const imgLeft = left - (imgWidth / 2);

        const parser = new DOMParser();
        const svgElement = parser.parseFromString(svgLogoData, "image/svg+xml");
        console.log({svgElement});

        doc.svg(svgElement, {x: imgLeft, y: 0.1, width: imgWidth, height: .889}).then(() => {
            doc.setDisplayMode('fullheight');
            const objectURL = doc.output('datauristring');
            setPDFSrc(objectURL)
        });
};
...

Also tried this:

import logo from '../../assets/logo.svg';
...
const svgElement2 = <img src={logo} alt="Logo"/>;
doc.svg(svgElement2, {x: imgLeft, y: 0.1, width: imgWidth, height: .889}).then(() => {
    doc.setDisplayMode('fullheight');
    const objectURL = doc.output('datauristring');
    setPDFSrc(objectURL)
});

That second method throws this in the console: Uncaught (in promise) TypeError: this.rootSvg.querySelectorAll is not a function

yGuy commented 3 weeks ago

your "svgElement" is not an SvgElement, but rather a document.

Read the whole answer in the linked stackoverflow question and add .documentElement to your parser call.

Regarding the react stuff - svgElement2 also isn't an SVGElement, but an object that only makes sense to React.

Please use the Discussions to discuss issues in your code. If you find a bug in the library, create a test-case and open a new issue. Thanks.