forked from evancz/elm-architecture-tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SpinSquare.elm
112 lines (88 loc) · 2.42 KB
/
SpinSquare.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module SpinSquare (Model, Action, init, update, view) where
import Easing exposing (ease, easeOutBounce, float)
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 : Float
, animationState : AnimationState
}
type alias AnimationState =
Maybe { prevClockTime : Time, elapsedTime : Time }
init : (Model, Effects Action)
init =
( { angle = 0, animationState = Nothing }
, Effects.none
)
rotateStep = 90
duration = second
-- UPDATE
type Action
= Spin
| Tick Time
update : Action -> Model -> (Model, Effects Action)
update msg model =
case msg of
Spin ->
case model.animationState of
Nothing ->
( model, Effects.tick Tick )
Just _ ->
( model, Effects.none )
Tick clockTime ->
let
newElapsedTime =
case model.animationState of
Nothing ->
0
Just {elapsedTime, prevClockTime} ->
elapsedTime + (clockTime - prevClockTime)
in
if newElapsedTime > duration then
( { angle = model.angle + rotateStep
, animationState = Nothing
}
, Effects.none
)
else
( { angle = model.angle
, animationState = Just { elapsedTime = newElapsedTime, prevClockTime = clockTime }
}
, Effects.tick Tick
)
-- VIEW
toOffset : AnimationState -> Float
toOffset animationState =
case animationState of
Nothing ->
0
Just {elapsedTime} ->
ease easeOutBounce float 0 rotateStep duration elapsedTime
view : Signal.Address Action -> Model -> Html
view address model =
let
angle =
model.angle + toOffset model.animationState
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!" ]
]
]