1

Let's say I have made an svg image in Elm:

svg [ viewBox "0 0 100 100" ] [ circle [ cx "60", cy "60", r "50" ] [] ]

How do I go about saving that image?

Just embedding it in html and right clicking doesn't work; and I can't find any other way to use it.

edit:

The "best" I've gotten so far is to use inspect mode and copy the generated html, save that as a file manually. This was enough to unblock me currently. Obviously that could be scripted with JavaScript, but I'm looking for an Elm solution.

The actual usecase I have is that I generate an identicon in Elm; like for instance Phace; my own package though, since the images should make sense in my app.

I want to be able to save the actual image, rather than the data used to generate it. Converting it to a png would be fine for this, though I prefer an svg.

Odalrick
  • 645
  • 5
  • 16
  • Do you mean saving it as a png or jpg? Or, do you mean saving it as an svg? Because it is already an svg and you just have to save what you have posted as a file. – Software Engineer May 08 '21 at 12:55
  • And how do I do that? I just cant find an interface that allows me to do that. The "best" I've gotten so far is to use inspect mode and copy the generated html, save that as a file manually. – Odalrick May 08 '21 at 13:47
  • I don't think there is a way to do this from within elm - even with [`file`](https://package.elm-lang.org/packages/elm/file/latest/File) as you cannot get at the content of the `Svg`/`Html`/`Node` representations like this - but you can write a port-Cmd and have native *JavsScript* grab and save the content for you (plenty of questions about this here I think - this should be an example: https://stackoverflow.com/questions/2483919/how-to-save-svg-canvas-to-local-filesystem) – Random Dev May 08 '21 at 17:39
  • I have no worries about being able to do it with JavaScript; but it's curious that there doesn't appear to be a native way to do it. If I _really_ want to do it, it should be easy enough to clone the api of the svg library and just render xml. Since I don't _need_ diffing at all. – Odalrick May 08 '21 at 19:05

1 Answers1

5

You can use elm-svg-string instead of the official SVG library and produce the string version of the SVG. You can then take the string version, encode it with Url.percentEncode and use it as the href for a download link and as src for an image in order to display it for preview purposes

module Main exposing (main)
 
import Browser
import Html exposing (Html, a, br, div, img, text)
import Html.Attributes exposing (download, href, src)
import Svg.String as Svg exposing (Svg)
import Svg.String.Attributes as Attr exposing (attribute,  viewBox)
import Url

someSvg : Svg.Html msg
someSvg =
    Svg.svg
        [ attribute "xmlns" "http://www.w3.org/2000/svg"
        , viewBox "0 0 100 100"
        ]
        [ Svg.circle
            [ Attr.cx "60"
            , Attr.cy "60"
            , Attr.r "50"
            , Attr.style "fill: red; stroke: blue"
            ]
            []
        ]


asString : String
asString =
    someSvg
        |> Svg.toString 2


asData =
    "data:image/svg+xml;utf8," ++ Url.percentEncode asString


main =
    div []
        [ text <| asString
        , br [] []
        , a [ download "image.svg", href asData ]
            [ img [ src asData ] [] ]
        ] 

In the above example, clicking on the image will result in the image being downloaded.

pdamoc
  • 2,798
  • 15
  • 19