在Elm中,我如何监听节点上生成的鼠标滚轮事件

Jam*_*ton 1 elm

请参阅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
Run Code Online (Sandbox Code Playgroud)

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

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

我很欣赏它可以通过端口来实现这一点,但是document.body当我只对在特定元素上发生的事情感兴趣时,抓住正在发生的事情似乎是错误的.

这种情况mousewheel是否只被视为文档级事件?

Dog*_*ert 6

该事件触发,但你的解码器失败,因为场event.deltaX,event.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))
Run Code Online (Sandbox Code Playgroud)

至:

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
        )   
Run Code Online (Sandbox Code Playgroud)