A module using the SVG graphics library to implement easily usable apps, which includes built-in functions for creating plain graphics, interactions, games and other applications including response to time, keyboard presses, and mouse actions.
graphicsApp : { view : GraphicSVG.Collage () } -> GraphicsApp
The simplest way to render graphics to the screen. These graphics will be
static (they don't move) and cannot be interacted with. This is great for beginners
or for when only need static graphics are needed. Note that your view
function is bare,
with no parameters:
view =
collage 500 500
[ circle 10 |> filled red
][ circle 10 |> filled red
]
graphicsApp
takes a parameter like { view = view }
so the main program that would get the whole thing started for the above
view
would be:
main =
graphicsApp { view = view }
GraphicSVG.App () () (HiddenMsg ())
This type alias is only used as a target for a user main
type signature
to make the type signature more clear and concise when main
calls
graphicsApp
:
main : GraphicsApp userMsg
main =
graphicsApp { view = view }
Note that userMsg
can be anything as no messages are used in this type of program.
notificationsApp : { model : userModel, view : userModel -> GraphicSVG.Collage userMsg, update : userMsg -> userModel -> userModel } -> NotificationsApp userModel userMsg
Like graphicsApp
, but you can add interactivity to your graphics by using the
notify*
functions. This allows you to learn Elm's architecture in a fun way with
graphics. Note that your view
function needs a model
parameter now, which in this
example is the colour of the shape:
view model =
collage 500 500
[ circle 10 |> filled model |> notifyTap Change
][ circle 10 |> filled model |> notifyTap Change
]
notificationsApp
takes a parameter like:
{
model = model
, view = view
, update = update
}
so the functions that would be required to make the above view
function work
are as follows:
type Msg
= Change
update msg model =
case msg of
Change ->
green
main =
notificationsApp
{ model = red -- causes circle to start red
, update = update -- function which changes the model
, view = view
}
which will cause the drawn red circle to change to green the first time
it is mouse clicked or tapped.
GraphicSVG.App () userModel (HiddenMsg userMsg)
This type alias is only used as a target for a user main
type signature
to make the type signature more clear and concise when main
calls
notificationsApp
:
main : NotificationsApp Model MyMsg
main =
notificationsApp { model = init, update = update, view = view }
where Model
is the type alias of the user persistent model, and
MyMsg
is the name of the user defined message type;
if other names are used, they can be substituted for these names.
gameApp : InputHandler userMsg -> { model : userModel, view : userModel -> GraphicSVG.Collage userMsg, update : userMsg -> userModel -> userModel, title : String } -> GameApp userModel userMsg
Automatically maps time and keyboard presses to your program. This should
be all you need for making complex interactive games and animations.
gameApp
takes two parameters: one is your own type of InputHandler
message
which will be automatically called each time the browser window is refreshed
(30 times per second)
of the form Float -> GetKeyState -> UserMsg
and the other is
{
model = model
, view = view
, update = update
}
The following program causes animation of the drawn line, causing it to spin around; also, a press of the "r" key causes the direction of the spin to reverse:
type Msg
= Tick Float GetKeyState
type alias Model = { angle : Float, speed : Float }
init = { angle = 0, speed = 1 }
update msg model =
case msg of
Tick _ ( keys, _, _ ) ->
case keys (Key "r") of
JustDown ->
{ model
| angle = model.angle - model.speed
, speed = -model.speed
}
_ -> { model | angle = model.angle + model.speed }
view model =
collage 500 500
[ line ( 0, 0 ) ( 250, 0 )
|> outlined (solid 1) green
|> rotate (degrees model.angle)
]
main =
gameApp Tick
{ model = init
, update = update
, view = view
}
GraphicSVG.App () ( userModel
, HiddenModel userMsg ) (HiddenMsg userMsg
}
This type alias is only used as a target for a user main
type signature to make
the type signature more clear and concise when main
calls gameApp
:
main : GameApp Model Msg
main =
gameApp Tick
{ model = init
, update = update
, view = view
}
where Tick
is the message handler called once per browser window update,
Model
is the type alias of the user persistent model, and
Msg
is the name of the user message type; if other names are used,
they can be substituted for these names.
Basics.Float -> GetKeyState -> userMsg
The InputHandler
type alias descripts a message that contains a Float representing the time in seconds from
the time the program started and the GetKeyState
type alias used for returning key actions.
This type is used for by the gameApp
fully interactive application.
( Keys -> KeyState
, ( Basics.Float
, Basics.Float )
, ( Basics.Float
, Basics.Float )
)
GetKeyState
returns a triple where the first argument is of type Keys -> KeyState
so you can ask if a certain key is pressed. The other two are tuples of arrow keys and
WASD keys, respectively. They're in the form (x,y) which represents the key presses
of each player. For example, (0,-1) represents the left arrow (or "A") key, and (1,1)
would mean the up (or "W") and right (or "D") key are being pressed at the same time.
Includes all the regular keys. Ask for letters and numbers using Key String
, e.g. Key "a"
or Key "3"
.
The possible states when you ask for a key's state:
JustDown
is the frame after the key went down (will show up exactly once per press)Down
is a press that is continuing for more than one frameJustUp
is the frame after the key went up / stopped being pressed (will show up exactly once per press)Up
means the key is not currently being pressed nor was it recently releasedGraphicSVG.App flags ( userModel
, HiddenModel userMsg ) (HiddenMsg userMsg
}
This type alias is only used as a target for a user main
type signature to make
the type signature more clear and concise when main
calls gameApp
:
main : GameApp Model Msg
main =
appWithTick Tick
{ model = init
, update = update
, view = view
, subscriptions = subscriptions
, onUrlRequest = OnUrlRequest
, onUrlChange = OnUrlChange
}
where Tick
is the message handler called once per browser window update,
Model
is the type alias of the user persistent model, and
Msg
is the name of the user message type; if other names are used,
they can be substituted for these names.
appWithTick : InputHandler userMsg -> { init : flags -> Url -> Browser.Navigation.Key -> ( userModel, Platform.Cmd.Cmd userMsg ), update : userMsg -> userModel -> ( userModel, Platform.Cmd.Cmd userMsg ), view : userModel -> { title : String, body : GraphicSVG.Collage userMsg }, subscriptions : userModel -> Platform.Sub.Sub userMsg, onUrlRequest : Browser.UrlRequest -> userMsg, onUrlChange : Url -> userMsg } -> AppWithTick flags userModel userMsg
A GraphicSVG.app with automatic time and keyboard presses passed into the update function.
appWithTick
takes two parameters: one is your own type of InputHandler
message
which will be automatically called each time the browser window is refreshed
(30 times per second)
of the form Float -> GetKeyState -> UserMsg
and the other is
```
{
init = model
, view = view
, update = update
, subscriptions = subscriptions
, onUrlRequest = OnUrlRequest
, onUrlChange = OnUrlChange
}
where init is the model and initial commands, view is a collage and a title,
update is the usual update function with commands, subscriptions are things
which you'd like to be notified about on a regular basis (e.g. changes in time,
incoming WebSocket messages), onUrlRequest is sent
whenever the user initiates a URL action (e.g. clicks a link) and onUrlChange
is when the user changes the url in the browser. See https://package.elm-lang.org/packages/elm/browser/latest/Browser#application
for a more clear description of these.