Skip to content

Instantly share code, notes, and snippets.

@jackofseattle
Created April 26, 2016 12:04
Show Gist options
  • Save jackofseattle/a1f658c67bd4b34fff6ec0f063189790 to your computer and use it in GitHub Desktop.
Save jackofseattle/a1f658c67bd4b34fff6ec0f063189790 to your computer and use it in GitHub Desktop.
Etch-a-sketch in Elm! Go to http://elm-lang.org/try and paste in this code.
-- Etch-a-sketch with Elm
-- Paste this code into http://elm-lang.org/try
-- Use the arrow keys to draw a line etch-a-sketch style
import Color exposing (..)
import Graphics.Collage exposing (..)
import Graphics.Element exposing (..)
import Keyboard
import Time exposing (fps)
-- New Types to work with
type alias Model =
{ points : List Point
, x : Int
, y : Int
}
type alias Point = (Int, Int)
-- This is all of the data for the app
initialModel : Model
initialModel =
{ points = [(0, 0)] -- all of the points we'll draw
, x = 0 -- current cursor position x and y
, y = 0
}
-- The view just translates the current model points into a canvas.
view : Model -> Element
view model =
collage 500 500 [(drawLine model.points)]
-- Functional piece - Elm takes care of the silly bitmap logic for us
drawLine : List Point -> Form
drawLine points =
let
intsToFloats (x, y) =
(toFloat x, toFloat y)
shape = path (List.map intsToFloats points)
in
shape
|> traced (solid blue)
-- As we know our model will change over time, lets convert it
-- into a stream that responds to our update function
model : Signal Model
model =
Signal.foldp update initialModel (pointsSignal Keyboard.arrows)
-- By default, signals are tiggered at the end of an event.
-- We want the line to coninuously draw, so we'll check for
-- key events 60 times per second instead.
pointsSignal : Signal {x :Int, y: Int} -> Signal {x :Int, y: Int}
pointsSignal keypresses =
Signal.sampleOn (fps 60) keypresses
-- Simple update function to add any new points into
-- the model
update : {x : Int, y: Int} -> Model -> Model
update arrows model =
let
newX = model.x + arrows.x
newY = model.y + arrows.y
in
{ model
| points = (newX, newY) :: model.points
, x = newX
, y = newY
}
-- Now just to render our application.
main : Signal Element
main = Signal.map view model
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment