如何在拖动元素时发送消息

时间:2015-10-24 18:37:43

标签: elm

我有一个相当简单的榆树应用程序

https://github.com/chrisortman/team-player

我无法弄清楚如何实现让我在表格单元格中单击并拖动其他几个单元格来选择它们的方法。

似乎onMouseOver是我想要的,但我不知道如何将它与Mouse.isDown信号结合起来。我可以将Mouse.isDown和Mouse.position结合起来,但后来我不知道如何将位置绑定到表格单元格。

我认为这个想法让我接近......

import Mouse
import Html exposing(..)
import Html.Attributes exposing(style)
import Html.Events exposing(onMouseOver,onClick)
import Signal exposing(..)

positionWithButton2 = 
  Signal.map3 (,,) Mouse.isDown Mouse.position mouseEvents.signal
  |> Signal.filterMap positionIfDown (0,0)

--positionWithButton = 
--  Signal.map2 (,) Mouse.isDown Mouse.position
--  |> Signal.map positionIfDown

font : List (String, String)
font =
    [ ("font-family", "futura, sans-serif")
    , ("color", "red")
    , ("font-size", "2em")
    ]

type ElementAction 
  = Hover Int
  | NoHover

mouseEvents = Signal.mailbox NoHover

background : List (String, String)
background =
    [ ("background-color", "rgb(245, 245, 245)")
    ]

positionIfDown (isDown,position,hover) =
  case (isDown,hover) of
  (True, Hover x) -> Just (x,x)
  (True, NoHover) -> Just position
  (False, Hover x) -> Just position
  _ -> Nothing


view pos =
  div [ ] 
    [ p [ style (font ++ background)] [text (toString pos)]
    , h1 [onMouseOver mouseEvents.address (Hover 10)]
        [text "Magic"]
    , Html.button
        [ onClick mouseEvents.address NoHover]
        [text "Stop"]
    ]

main : Signal Html
main =
  Signal.map view positionWithButton2

1 个答案:

答案 0 :(得分:3)

我担心,你需要做一些更多的事情。

在尝试使用elm版本之前,我们应该考虑在用户尝试拖动多个单元格时触发的javascript事件。

___________________
|(0,1)|(1,1)|(2,1)|
|_____|_____|_____| 
|(0,0)|(1,0)|(2,0)|
|_____|_____|_____|

假设某人开始从单元格(1,1)拖出。我们将收到一个初始mousedown事件,然后我们将开始接收mousemove个事件。当我们继续拖动到单元格(1,2)时会发生什么呢?好吧,(1,2) 不会收到'click'或'mousedown'事件,但mouseentermouseover会触发,mousemove应继续触发,我认为target属性将更改为单元格(1,2)

那么,我们需要做些什么来弄清楚榆树土地上的重点?我很容易看到你已经在使用elm-html了 - 我们将不得不大量使用它的Events部分。

N.B我在没有编译器的帮助下把它放在一起,所以可能会有一些错误;虽然形状感觉不错。

首先,我们需要这个代码段:

import Json.Decode exposing ((:=), Decoder)
targetId : Decoder String
targetId = ("target" := ("id" := J.string))        

这将解码给定事件中目标元素的id。

我们需要以下事件定义

data Event = SelectStart String
           | SelectContinue String
           | SelectCancel

和发送它们的邮箱

events : Signal.Mailbox (Event)
events = Signal.mailbox SelectCancel

需要为每个单元格提供一个id,其中包含坐标信息(cell-0-1cell-1-1等),以及以下事件:

import Html.Events exposing (on)

on 'mousedown' targetId (\id -> Signal.message events.address (SelectStart id))
on 'mousemove' targetId (\id -> Signal.message events.address (SelectContinue id))

这应该为您提供足够的信息,通过适当地处理events.signal上发生的事件来确定所选择的内容。 N.B您可能还希望在不启动另一个元素的情况下附加一些其他元素来取消现有选择;我不确定你想要达到的目的,但是: - )

您的模型应该有一个看起来有点像的字段:

type alias SelectRange = ((Int, Int), (Int, Int)) 

type alias Model = {
    selectState : Maybe SelectRange
}

当我们收到第一个SelectStart事件时,我们会根据id字符串计算坐标(假设它是(0,0)),并将selectState更改为Just ((0,0), (0,0))。然后SelectContinue事件开始出现;我们会在他们仍然引用(0, 0)时忽略它们,但是当一个人到达(0,1)时;我们检查现有的选择状态,并确定它现在应该是Just ((0,0),(0,1))。总共编写update函数很棘手(用户可能会向一个方向拖动然后反向),但并非不可能。

假设所选单元格与未选择单元格的呈现方式不同,我们可以将selectState移交给视图函数,并且在渲染每个单元格时,它可以检查它是否被选中并且行为正确

我希望有足够的信息让你前进;如果有任何不清楚的地方,请询问: - )