在Elm中,我如何监听节点

时间:2018-05-15 10:52:47

标签: elm

请参阅以下示例on Ellie

module Main exposing (main)

import Html exposing (..)
import Html.Attributes exposing (style)
import Html.Events exposing (Options, onClick, onWithOptions)
import Json.Decode as JD
import Json.Decode.Extra exposing ((|:))
import Result exposing (withDefault)
import String as S


main : Program Never Model Msg
main =
    Html.program
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view
        }


init : ( Model, Cmd Msg )
init =
    ( Model "", Cmd.none )


type alias Model =
    { message : String
    }


type Msg
    = Zoom MouseWheelEvent
    | Clicked


type alias MouseWheelEvent =
    { deltaX : Float
    , deltaY : Float
    , clientX : Float
    , clientY : Float
    }



update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Zoom e ->
            ( { model | message = toString e }, Cmd.none )
        Clicked ->
            ( { model | message = "Clicked!" }, Cmd.none )


decodeMouseEvent : JD.Decoder Msg
decodeMouseEvent =
    JD.map Zoom
        (JD.succeed MouseWheelEvent
            |: mouseAttribute "deltaX"
            |: mouseAttribute "deltaX"
            |: mouseAttribute "deltaX"
            |: mouseAttribute "deltaX"
        )


mouseAttribute : String -> JD.Decoder Float
mouseAttribute k =
    JD.at [ k ] JD.string |> JD.andThen readFloat


readFloat : String -> JD.Decoder Float
readFloat n =
    JD.succeed (withDefault 0 (S.toFloat n))


view : Model -> Html Msg
view m =
    div []
        [ p [] [ text <| "message: " ++ m.message ]
        , div
            [ onWithOptions "mousewheel" (Options True True) decodeMouseEvent
            , onClick Clicked
            , style
                [ ( "height", "250px" )
                , ( "width", "250px" )
                , ( "background-color", "green" )
                ]
            ]
            [ p [] [ text "Zoom here" ]
            ]
        ]


subscriptions m =
    Sub.none

我想捕获特定元素上的mousewheel事件。这与在SVG图像上创建缩放效果有关。

根据示例,如果我将侦听器附加到特定元素,则不会调用update函数。该事件似乎被文档正文捕获,但未达到我的目标元素。那么如何让我的事件处理程序触发?

我很欣赏它可以通过端口执行此操作,但是当我只对在特定元素上发生时捕获它时,抓住在document.body级别发生的事情似乎是错误的。

是否只将mousewheel视为文档级事件?

1 个答案:

答案 0 :(得分:6)

事件触发,但您的解码器失败,因为字段event.deltaXevent.deltaY等不是字符串而是浮点数。如果解码器失败,AFAIK Elm会默默地忽略该事件。如果我改变解码器,它可以工作:

decodeMouseEvent : JD.Decoder Msg
decodeMouseEvent =
    JD.map Zoom
        (JD.succeed MouseWheelEvent
            |: mouseAttribute "deltaX"
            |: mouseAttribute "deltaX"
            |: mouseAttribute "deltaX"
            |: mouseAttribute "deltaX"
        )


mouseAttribute : String -> JD.Decoder Float
mouseAttribute k =
    JD.at [ k ] JD.string |> JD.andThen readFloat


readFloat : String -> JD.Decoder Float
readFloat n =
    JD.succeed (withDefault 0 (S.toFloat n))

为:

decodeMouseEvent : JD.Decoder Msg
decodeMouseEvent =
    JD.map Zoom
        (JD.succeed MouseWheelEvent
            |: JD.field "deltaX" JD.float
            |: JD.field "deltaY" JD.float
            |: JD.field "clientX" JD.float
            |: JD.field "clientY" JD.float
        )