Json 解码器不起作用的原因很明显,因为
没有offsetLeft
nor offsetTop
存在于
事件对象。
这有点令人困惑,因为这些属性都是可用的
适用于 Html DOM 的单击事件,但不适用于 SVG DOM。
(我的建议是
在 Elm 中实现事件解码器是附加临时的
浏览器调试器控制台中的事件处理程序并研究实际的事件对象。 Elm 的解码器无声地失败并且很难知道解码器的原因
不工作。
)
在这里,我实现了另一种使用方法port
要得到
使用 javascript 的父位置(不使用任何
社区图书馆)。
port module Main exposing (main)
import Html exposing (Html, div)
import Html.App as App
import Html.Attributes
import Html.Events exposing (on)
import Json.Decode as Json exposing (object2, object1, int, at)
import Mouse exposing (Position)
import Svg exposing (svg, rect)
import Svg.Attributes exposing (..)
main : Program Never
main =
App.program
{ init = (initmodel, getParentPos ())
, view = view
, update = update
, subscriptions = subscriptions
}
type alias Model =
{ position : Position
, parentPosition : Position
}
type Msg
= ChangePosition Position
| UpdateParentPosition { top : Int, left : Int }
initmodel : Model
initmodel =
{ position = Position 0 0
, parentPosition = Position 0 0
}
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case Debug.log "msg" msg of
ChangePosition position ->
let
relativepos = Position
( position.x - model.parentPosition.x )
( position.y - model.parentPosition.y )
in ({ model | position = relativepos } , Cmd.none)
UpdateParentPosition {top, left} ->
({ model | parentPosition = Position top left }, Cmd.none)
port getParentPos : () -> Cmd msg
subscriptions : Model -> Sub Msg
subscriptions model =
parentPos UpdateParentPosition
port parentPos : ({ top : Int, left : Int } -> msg) -> Sub msg
view : Model -> Html Msg
view model =
div []
[ svg
[ width "400"
, height "100"
, viewBox "0 0 400 100"
, id "parent"
]
[ rect
[ onClickLocation -- this should work but does nothing
, width "400"
, height "100"
, x "0"
, y "0"
, fill "#000"
, cursor "pointer"
]
[]
, rect
[ width "50"
, height "50"
, x (toString model.position.x)
, y (toString model.position.y)
, fill "#fff"
]
[]
]
, div
[ onClickLocation -- this works
, Html.Attributes.style
[ ( "background-color", "white" )
, ( "border", "2px solid black" )
, ( "width", "400px" )
, ( "height", "100px" )
, ( "position", "absolute" )
, ( "left", "0px" )
, ( "top", "150px" )
, ( "color", "black" )
, ( "cursor", "pointer" )
]
]
[ div [] [ Html.text "Click in here to move x position of white svg square. Relative click coordinates shown below (y coordinate ignored)." ]
, div [] [ Html.text (toString model) ]
]
]
onClickLocation : Html.Attribute Msg
onClickLocation =
on "click"
(Json.map
ChangePosition
(object2
Position
(at [ "pageX" ] int)
(at [ "pageY" ] int)
)
)
javascript:
const app = Elm.Main.fullscreen();
app.ports.getParentPos.subscribe(() => {
const e = document.querySelector('#parent');
const rect = e.getBoundingClientRect();
app.ports.parentPos.send({
top: Math.round(rect.top),
left: Math.round(rect.left)
});
});