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.
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.
Related
How do I get the caption from a button?
decorateOn : String -> Html Msg -> Html Msg
decorateOn selectedCaption button =
if button.text == selectedCaption then
button [ class "selectedNavigationButton" ] []
else
button [ class "navigationButton" ] []
button does not have a field named text. - The type of button
is:
Html Home.Msg
Which does not contain a field named text.
Note, I realize that the "button" is really of type Html Msg.
You need to turn your thinking on its head. Rather than seeing what is in the button text, you need to set the text at the same stage as setting the class. So that gives you something like
decorateOn : String -> Html Msg -> Html Msg
decorateOn selectedCaption button =
if selectedCaption == "the selected value" then
button [ class "selectedNavigationButton" ] [text selectedCaption ]
else
button [ class "navigationButton" ] [text selectedCaption]
You can't get the text from a button without resorting to hacks involving ports and JavaScript. Moreover, you can't really inspect anything about the Elm Virtual DOM from within Elm.
Instead, try to refactor your app so that you can get the information from your model.
I am trying to place my html view in the middle of a container.
Unfortunately, container gives output of type Graphics.Element.Element whereas html view must be of the type, Html.Html.
And also, the html element constructors like div, checkbox, button, body return type is Html whereas, container needs a Graphics.Element parameter.
This is an erroneous html view, which i would like to make it work,
view : Signal.Address Action -> Model -> Element
view address model =
container 1000 1000 middle <|
toForm <|
div []
[ button [ onClick address Decrement ] [text "-"]
, div [ countStyle ] [ text (toString model ) ]
, button [ onClick address Increment ] [ text "+" ]
]
It has two buttons, one div all placed in the middle of a 1000 * 1000 container.
The elm-html package has a fromElement that can be used to create an Html from an Element.
I will say though, the idea with elm-html is to allow for a more "normal" flow of rendering HTML and using CSS to style it. While it would work to take your Html, convert it to an to either a Form or Element, use a collage or container to move it to the center of some area, and then convert back to Html, I'd probably recommend against it. If you're using HTML, just render that and style it (either with an external stylesheet or withHtml.Attributes).
For some reason when I run my code - or even the example codes from the Rebol website - the font size of the GUI text do not have an effect. I can write:
view layout [ text "This should be big!" font [size: 50] ]
or even:
view layout [ text "This should also be big!" font-size 50 ]
but neither do anything. Peculiarly, however, I can add a color to the text.
I create links for a website in Elm with Text.link "https://somewebsite.com" (toText "SomeWebsite"). I would like to be able to set the color of the resultant text.
I have tried Text.link "https://somewebsite.com" (Text.color white <|toText "SomeWebsite") and Text.color white <|Text.link "https://somewebsite.com" (toText "SomeWebsite"), neither of which work, despite that the type signature of link is link : String -> Text -> Text. Both of these snippets compile.
I've looked through the source of elm-lang.org, which has links that look like they've been styled (they seem to have a different color than the default dark blue and no underlines) and haven't found anything that explains how it's done there.
How can I color the text of links in Elm?
The following will create a link to google that is red:
import Text (..)
main = toText "Google"
|> style {defaultStyle | color <- red, height <- Just 20 }
|> link "http://google.com"
|> leftAligned
Live demo here.
Unfortunately, this does not give you the power to really "style" the link when you hover over it which is a bit of a bummer.
The elm-lang website has the following styles at the top of its pages:
<style type="text/css">
a:link {text-decoration: none; color: rgb(15,102,230);}
a:visited {text-decoration: none}
a:active {text-decoration: none}
a:hover {text-decoration: underline; color: rgb(234,21,122);}
body { font-family: "Lucida Grande","Trebuchet MS","Bitstream Vera Sans",Verdana,Helvetica,sans-serif !important; }
p, li { font-size: 14px !important;
line-height: 1.5em !important; }
</style>
This gives its links the styling you see there.
However, it is still possible to get this type of styling using customButton from Graphics.Input.
import Graphics.Input as Input
click = Input.input ()
linkFormat = { defaultStyle | color <- blue }
hoverFormat = { linkFormat | bold <- True }
customLink url text =
let text' = Text.toText text
regular = Text.style linkFormat text' |> leftAligned
hover = Text.style hoverFormat text' |> leftAligned
down = Text.style linkFormat text' |> leftAligned
in link url <| Input.customButton click.handle () regular hover down
main = customLink "http://google.com" "Google"
Live demo here.
One thing to notice here is that I am not using Text.link. I am just using the link function from Graphics.Element which is imported by default and has the type String -> Element -> Element.
I hope this helps!
This no longer works on Elm 0.13, btw. It first says link is ambiguous between the one in the Graphics lib and the Text.link, so I qualify it by prepending Text. to link and then it complains that it 'Could not find variable 'Text.link'.' Same thing happens when I qualify it as a Graphics.Element.link.
it seems weird that I would not be able to qualify something by adding the module qualifier to it in Elm 0.13.
To accomplish this in 0.13, I figured out you can do the below.
import Text
main = link "http://www.google.com" <| leftAligned <| Text.color red <| toText "Google"
http://share-elm.com/sprout/5430943ee4b017b21db2f86c
Demo in Elm-0.18
module Main exposing (main)
import Html as H exposing (Html)
import Html.Attributes as HA
main : Html msg
main =
H.a
[ HA.href "https://en.wikipedia.org"
, HA.style [ ( "color", "green" ) ]
]
[ H.text "wikipedia" ]
Default Rebol VID style is eye-searing, put bluntly. I started making my own default, but ran into a snag. Namely, how do I specify styles for a sub-element of an element?
good-looking: stylize [
field: field
edge [size: 1x1]
colors [255.255.255 255.255.255]
area: area
edge [size: 1x1]
colors [255.255.255 255.255.255]
text-list: text-list
;text-list/sub-area/edge [size: 1x1]
]
I want all fields to have a thin border, including text-list and others. But I have no idea how to include that rule in the text-list definition.
Also, how to reduce repetition with styles, like with the colors?
I can partly answer your first question. At the REBOL consol, try this...
>> lo: layout [t: text-list]
That both creates a layout and allows the text-list object (t) to be examined using PROBE...
>> probe first t
== [self type offset size span pane text color image effect data edge font para feel saved-area rate show? options parent-face old-offset old-size line-list changes face-flags action state access style alt-action facets related words colors texts images file var keycode reset styles init multi blinker pane-size dirty? help user-data flags doc xy sz iter sub-area sld sn lc picked cnt act slf lines text-pane update resize]
Notice the SUB-AREA there. That's the list area in a text-list. Probe into that and you get...
>> probe first t/sub-area/edge
== [self color image effect size]
>> probe first t/sub-area/edge/size
== 2
So, change SIZE there and view the layout we made...
>> t/sub-area/edge/size: 1x1
== 1x1
>> view lo
The text-list's edge should be thin now. I'm not sure how you achieve that using style, but hopefully this will put you on the right track.
So, first:
layout [X: field]
type? X/edge
type? X/colors
Objects should get re-made to avoid unexpected side-effects on the shared ones.
good-looking: stylize [
field: field with [
edge: make edge [size: 1x1]
colors: copy [255.255.255 255.255.255]
]
area: area with [
edge: make edge [size: 1x1]
colors: copy [255.255.255 255.255.255]
]
text-list: text-list with [
sub-area: make sub-area [
edge: make edge [size: 1x1]
]
]
]