Elm resizeable SVG canvas filling the screen

I am toying with writing an SVG-based game in (exciting-looking JavaScript-replacement) Elm, and I wanted an SVG that filled the whole screen and resized when the screen resized. I found it harder than I expected, so here is what I came up with for your information and comment.

Try the demo.

Because I was using Html.App.programWithFlags I was not able to shortcut the process and use just elm-reactor – I needed to create an HTML file and compile my code with elm-make.

index.html sets up a full-screen app and passes in the window size:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8"/>
    <title>Sootl</title>
    <script src="sootl.js"></script>
    <style>
        html, body, svg
        {
            margin: 0px;
            padding: 0px;
            border: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>
</body>
<script>
var app = Elm.Main.fullscreen(
    {
        width:  window.innerWidth,
        height: window.innerHeight
    }
);
</script>
</html>

elm-package.json requires the Html, Svg and Window packages:

{
    "version": "1.0.0",
    "summary": "Stay out of the light!",
    "repository": "https://github.com/andybalaam/sootl.git",
    "license": "GPL2",
    "source-directories": [
        "."
    ],
    "exposed-modules": [],
    "dependencies": {
        "elm-lang/core": "4.0.5 <= v < 5.0.0",
        "elm-lang/html": "1.1.0 <= v < 2.0.0",
        "elm-lang/svg": "1.1.1 <= v < 2.0.0",
        "elm-lang/window": "1.0.0 <= v < 2.0.0"
    },
    "elm-version": "0.17.1 <= v < 0.18.0"
}

Main.elm contains the Elm code, which starts off with the window size from JavaScript, and then listens to resize events using the Window module.

import Html exposing (Html)
import Html.App exposing (programWithFlags)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import Window


type alias Flags =
    { width : Int
    , height : Int
    }


type Msg = Resize Int Int


type alias Model =
    { screen :
        { width : Int
        , height : Int
        }
    }


init : Flags -> (Model, Cmd Msg)
init flags =
    (
        { screen =
            { width = flags.width
            , height = flags.height
            }
        }
    , Cmd.none
    )



view : Model -> Html Msg
view model =
    let
        sw = model.screen.width  - 0
        sh = model.screen.height - 0
    in
        svg
        [ width  <| toString sw
        , height <| toString sh
        ]
        [ rect
            [ x "0"
            , y "0"
            , width (toString model.screen.width)
            , height (toString model.screen.height)
            , fill "#eeffee"
            ]
            []
        , text'
            [ x <| toString <| sw / 2
            , y <| toString <| sh / 2
            , fontSize <| toString <| sh / 10
            , textAnchor "middle"
            ]
            [ text
                ((toString model.screen.width)
                ++ ", "
                ++ (toString model.screen.height))
            ]
        ]


update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    let m =
        case msg of
            Resize w h -> {model | screen = {width = w, height = h}}
    in
        (m, Cmd.none)


subscriptions : Model -> Sub Msg
subscriptions model =
    Window.resizes (\size -> Resize size.width size.height)


main =
   programWithFlags
     { init = init
     , view = view
     , update = update
     , subscriptions = subscriptions
     }

I installed all the packages with:

elm-package install

Then I compiled the code with:

elm-make --output=sootl.js Main.elm

Now I launched elm-reactor:

elm-reactor

And navigated my browser to http://localhost:8000/index.html to see it working.

Elm Basics Video

Series: Snake in Elm, Elm makes me happy, Elm Basics, Elm Unit Test, Elm JSON

A lot of the documentation about the new language I am really excited about, Elm focusses on the Elm Architecture and the ideas of Functional Reactive Programming, and while those are the fundamental reasons I am interested in Elm, I found myself stuck on the syntax quite often.

So, in this video I review almost all the syntax and basic ideas you need to be able to read and write Elm code, treating it as a general programming language.

Update: forgot to add the slides – here they are:
Slides: Elm Basics

Elm makes me happy (old: Elm 0.17)

Updated version: Elm makes me happy (updated for Elm 0.19)

Elm lets you write interactive web sites in a really clean and safe-feeling way, which is a contrast to the feeling I get when using JavaScript and HTML. It’s functional, but instead of that making everything seem hard, it makes me happy.

Slides: Elm makes me happy

Snake in Elm

Snake Series: Groovy, Ruby, BASIC, Dart, Elm, Python3+Qt5

Elm Series: Snake in Elm, Elm makes me happy, Elm Basics, Elm Unit Test, Elm JSON

I’m writing the game Snake in lots of programming languages, for fun, and to try out new languages.

Elm brings the comfortable feeling and scary syntax of a pure functional language to writing dynamic web sites.

Slides: Snake in Elm

If you want to, you can Support me on Patreon.