Elm のイベント用の関数は onClick
など主だったものはライブラリで用意されていますが、それ以外のイベントは on
関数を利用して自分で合成する必要があります。
以下、合成方法の覚書です。
mousemove イベントをハンドリングする
イベントの値を受け取る型を用意します。
type Msg = Move Int Int
イベントのデコーダを用意します。
mousemove
イベントのうち clientX
と clientY
の二つのフィールドをそれぞれ Int
として取得し、Move
を適用するデコーダです。
map2 Move (field "clientX" int) (field "clientY" int)
map2
, field
, int
は Json.Decode
で定義されている関数です。
動作を REPL で確認してみます。
$ elm repl ---- Elm 0.19.0 ---------------------------------------------------------------- Read <https://elm-lang.org/0.19.0/repl> to learn more: exit, help, imports, etc. -------------------------------------------------------------------------------- > import Json.Decode exposing(map2, field, int, decodeString) > type Msg = Move Int Int > decodeString (map2 Move (field "clientX" int) (field "clientY" int)) "{\"clientX\":10,\"clientY\":20}" Ok (Move 10 20) : Result Json.Decode.Error Msg >
{"clientX":10,"clientY":20}
という JSON から Move 10 20
という値を取得することができました。
このデコーダを on
関数に与えます。
イベントの構造については MDN などを参照してください。
実装
div 要素上のマウスカーソルの位置を表示するだけのサンプルです。
import Browser import Html exposing (Html, div, span, text) import Html.Events exposing (on) import Html.Attributes exposing (style) import Json.Decode exposing (map2, field, int) main = Browser.sandbox { init = init , update = update , view = view } type alias Model = { x: Int , y: Int } init : Model init = { x = 0 , y = 0 } type Msg = Move Int Int update : Msg -> Model -> Model update msg model = case msg of Move x y -> {x = x, y = y} view : Model -> Html Msg view model = div [] [ span [] [ text ("(" ++ (String.fromInt model.x) ++ ", " ++ String.fromInt model.y ++ ")") ] , div [ style "background-color" "gray" , style "height" "80vh" , on "mousemove" (map2 Move (field "clientX" int) (field "clientY" int)) ] [] ]
合成する関数に名前をつける
見通しをよくするために名前をつけます。ここでは Move
を引数で受け取るようにすることで他のメッセージにも利用できるようにしています。
-- view 以外は上と同じ view : Model -> Html Msg view model = div [] [ span [] [ text ("(" ++ (String.fromInt model.x) ++ ", " ++ String.fromInt model.y ++ ")") ] , div [ style "background-color" "gray" , style "height" "80vh" , onMouseMove Move ] [] ] onMouseMove : (Int -> Int -> msg) -> Html.Attribute msg onMouseMove f = on "mousemove" (map2 f (field "clientX" int) (field "clientY" int))