exupero / saveSvgAsPng

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

SVG to PNG not render images in Safari browser #223

Open saulacher opened 4 years ago

saulacher commented 4 years ago

Hi, i have a problem with downloading svg as png in Safari. In Chrome works fine but in Safari sometimes (not every time) images in svg not rendering in final png.

https://jsfiddle.net/fvkjyLw4/

correct png (Chrome) image (2)

wrong png (Safari) image-2

ryanfitzer commented 4 years ago

I am also able to reproduce this issue, both in my own codebase and the example from @saulacher above.

Safari: 12.1.1 (14607.2.6.1.1) macOS: 10.14.5 (18F132)

It almost always happens on the first download. Successive downloads often yield the full svg as expected, but not always.

BartvanS commented 4 years ago

I experience the same problem but with tspan in text

ryanfitzer commented 4 years ago

Looking into this more, I see that Safari makes a new request for all linked assets. Here's a screenshot of the example shared by @saulacher (with the downloaded result showing in the upper right corner).

Before clicking the "Save" button, I cleared all network requests from the log. As you can see, the 3 jpgs are requested again. My sense is that these resources are not yet downloaded when the png is created and therefore, do not show in the result.

Screenshot 2019-08-15 16 54 12

But when I click the "Save" button a second time, the 3 jpgs are not requested again and the png shows as expected.

This aligns with my own case. The parts that don't show initially are <text> elements that use webfonts. The webfonts are requested on the first click of "Save", but don't show. It takes another click to download the png in order to get the <text> elements to show in the png.

When I switch out the webfonts for a system font (Helvetica), the <text> elements show on the first png download.

Not yet sure what the solution is, but wanted to post my progress in the hopes it helps move this closer to a solution.

ryanfitzer commented 4 years ago

Update: Looks like Chrome also makes requests, but some are pulled from cache. Still confused...

ryanfitzer commented 4 years ago

I've narrowed it down to this line. From what I can find elsewhere, Safari has issues rendering linked assets when the canvas element is first drawn.

In the source, just after the line I linked to, if you run document.body.appendChild() on both canvas and src (which is an image with the svg dataURI as its src), you'll find that in Safari 12, the src image renders the fonts, but the canvas doesn't. Running saveSvgAsPng a second time shows the fonts/images rending correctly.

While it's not ideal, I've found a workaround. To force the PNG to be generated twice, but dowloaded only once, I first running svgAsPngUri and saveSvgAsPng in the returned promise's .then(). I've forked the example @saulacher posted as an example: https://jsfiddle.net/2hpok9uj/. This works in Safari. But as I said, it's not ideal.

ligaz commented 4 years ago

It looks like it might be a bug in WebKit. You can file an issue here.