Source
module Clock exposing (main)
-- Show an analog clock for your time zone.
--
-- Dependencies:
-- elm install elm/svg
-- elm install elm/time
--
-- For a simpler version, check out:
-- https://elm-lang.org/examples/time
--
import Browser
import Html exposing (Html)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import Task
import Time
-- MAIN
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ zone : Time.Zone
, time : Time.Posix
}
init : () -> (Model, Cmd Msg)
init _ =
( Model Time.utc (Time.millisToPosix 0)
, Cmd.batch
[ Task.perform AdjustTimeZone Time.here
, Task.perform Tick Time.now
]
)
-- UPDATE
type Msg
= Tick Time.Posix
| AdjustTimeZone Time.Zone
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Tick newTime ->
( { model | time = newTime }
, Cmd.none
)
AdjustTimeZone newZone ->
( { model | zone = newZone }
, Cmd.none
)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Time.every 1000 Tick
-- VIEW
view : Model -> Html Msg
view model =
let
hour = toFloat (Time.toHour model.zone model.time)
minute = toFloat (Time.toMinute model.zone model.time)
second = toFloat (Time.toSecond model.zone model.time)
in
svg
[ viewBox "0 0 400 400"
, width "400"
, height "400"
]
[ circle [ cx "200", cy "200", r "120", fill "#1293D8" ] []
, viewHand 6 60 (hour/12)
, viewHand 6 90 (minute/60)
, viewHand 3 90 (second/60)
]
viewHand : Int -> Float -> Float -> Svg msg
viewHand width length turns =
let
t = 2 * pi * (turns - 0.25)
x = 200 + length * cos t
y = 200 + length * sin t
in
line
[ x1 "200"
, y1 "200"
, x2 (String.fromFloat x)
, y2 (String.fromFloat y)
, stroke "white"
, strokeWidth (String.fromInt width)
, strokeLinecap "round"
]
[]