Search code examples
elm

How do I save an svg image


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.


Solution

  • 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.