Skip to content

Instantly share code, notes, and snippets.

@mgold
Created September 24, 2015 23:05
Show Gist options
  • Save mgold/399923b7acd29b236b3b to your computer and use it in GitHub Desktop.
Save mgold/399923b7acd29b236b3b to your computer and use it in GitHub Desktop.
module SpinSquare (Model, Action, init, update, view) where
{-| A fork of the eight example in the Elm Architecture tutorial, showing how it would be done with elm-animation. It
turns out to be a lot simpler, both because of the animation itself and because we cheat a little: we don't stop
asking for clock ticks even when we don't need them. This saves a lot of bookkeeping around current vs. elapsed
time, as the animation library assumes you have a constantly running clock shared among all components.
By definition, encapsulated components cannot share a clock, and so as you add more squares, expect things to get
slower. That said, two squares work just fine. This module is a drop-in replacement for the upstream version.
Excercise for the reader: change `update` to turn off the clock when the square is done rotating, and account for
the fact that when you turn the clock back on, it will have counted the intervening time.
Base fork: https://github.com/evancz/elm-architecture-tutorial/tree/master/examples/8
Animation library: https://github.com/mgold/elm-animation
Add as a dependency: "mgold/elm-animation": "1.0.1 <= v < 2.0.0",
-}
import Animation exposing (Animation)
import Easing exposing (easeOutBounce)
import Effects exposing (Effects)
import Html exposing (Html)
import Svg exposing (svg, rect, g, text, text')
import Svg.Attributes exposing (..)
import Svg.Events exposing (onClick)
import Time exposing (Time, second)
-- MODEL
type alias Model =
{ angle : Animation
, clock : Time
}
effects : Effects Action
effects = Effects.tick Tick
init : (Model, Effects Action)
init =
( { angle = Animation.static 0 |> Animation.ease easeOutBounce |> Animation.duration second, clock = 0 }
, effects
)
rotateStep = 90
-- UPDATE
type Action
= Spin
| Tick Time
update : Action -> Model -> (Model, Effects Action)
update msg model =
case msg of
Spin ->
if Animation.isRunning model.clock model.angle
then ( model, Effects.none )
else let currentAngle = Animation.getTo model.angle
newAnimation = Animation.retarget model.clock (currentAngle + rotateStep) model.angle
newModel = { angle = newAnimation, clock = model.clock }
in ( newModel, effects)
Tick newClock ->
let newModel = { angle = model.angle, clock = newClock }
in ( newModel , effects )
-- VIEW
view : Signal.Address Action -> Model -> Html
view address model =
let
angle = Animation.animate model.clock model.angle
in
svg
[ width "200", height "200", viewBox "0 0 200 200" ]
[ g [ transform ("translate(100, 100) rotate(" ++ toString angle ++ ")")
, onClick (Signal.message address Spin)
]
[ rect
[ x "-50"
, y "-50"
, width "100"
, height "100"
, rx "15"
, ry "15"
, style "fill: #60B5CC;"
]
[]
, text' [ fill "white", textAnchor "middle" ] [ text "Click me!" ]
]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment