exupero / saveSvgAsPng

Save SVGs as PNGs from the browser.
MIT License
1.09k stars 362 forks source link

Ignores :first-child selector #159

Closed esomkin closed 6 years ago

esomkin commented 6 years ago

Hi!

I need to export simple SVG element (two rectangles) into PNG format. First rectangle has red color, last is green. In browser all ok, but in export file first rectangle is black.

Test code is here

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <style>
        .svg-root{}
            .svg-root > rect{}
            .svg-root > rect:first-child{
                fill: #f00;
            }
            .svg-root > rect:last-child{
                fill: #0f0;
            }
        </style>
    </head>
    <body>
        <svg class="svg-root" width="200" height="200">
            <rect class="rect1" x="0" y="0" width="100" height="100"></rect>
            <rect class="rect2" x="100" y="100" width="100" height="100"></rect>
        </svg>
        <a href="/" class="export">Export</a>
        <script src="https://code.jquery.com/jquery-latest.js"></script>
        <script src="saveSvgAsPng.js"></script>
        <script>
            $(document).on('ready', function (e) {
                $('.export').on('click', function (e) {
                    e.preventDefault();
                    saveSvgAsPng(document.querySelector('.svg-root'), 'test.png', { modifyStyle: (opt) => {
                        return opt;
                    }});
                });
            });
        </script>
    </body>
</html>

How can I paint a rectangles in correct colors? There is no possibility to assign class or id to rectangles.

Thanks in advance.

exupero commented 6 years ago

Hi, thanks for the clear example case. That made it very easy to figure out what the problem is.

The :first-child CSS isn't getting applied to the rectangle because the exported SVG's first child is a <defs> element that defines all the styles. rect:first-child doesn't match, but rect:nth-child(2) does.

I suggest you wrap your rects in a g tag with a known class that you can use in your selector. Then :first-child will work as expected.

At the moment I'm not sure what a better solution is, but I'm open to suggestions.

esomkin commented 6 years ago

Thank you for your clarification! But, how is you understand that the first child is <defs>? Did you using some debug tool to see exported result SVG?

exupero commented 6 years ago

You can get the SVG code with the prepareSvg function. For example,

prepareSvg(document.querySelector('.svg-root'), {}, svg => console.log(svg));
esomkin commented 6 years ago

Thank you very much!