榆树+ Masonry.js

Geo*_*rge 2 elm masonry

我试图通过端口获得与Masonry.js集成的Elm应用程序,但是我无法弄清楚如何获取Signal Html来触发告诉Masonry.js重绘视图的端口.

我正在使用StartApp,我不知道如何从更新调用中获取视图已完成重新呈现的信号.

可以使用Elm或完全Elm解决方案更好地工作的替代库也将受到赞赏.

关于我正在尝试解决的整体问题的更多细节:我有一系列图像,我想以砖石格式(http://masonry.desandro.com/)进行平铺.它们由Elm中的对象列表表示,它们被转换为视图中的div列表(适当地设置了背景图像),但是图像具有不同的大小,因此希望很好地平铺它们.我正在使用StartApp(http://package.elm-lang.org/packages/evancz/start-app/2.0.2/)来抽象html的实际呈现.

Cha*_*ert 7

您可以使用Elm中的端口与javascript通信,以便在两个方向上发布和订阅事件.让我们构建一个示例,其中图像列表以砖石布局显示,单击图像将删除它并触发砌体布局剩余图像.

由于Elm应用程序将向javascript发送多种类型的事件,我们可以创建一个发送字符串的单个端口,然后javascript可以对其进行操作.这些字符串将是我们可以在javascript中解释的命令,以告诉砌体做某些事情,比如"initialize""imageRemoved".此端口还需要一个邮箱,我们可以从Elm内部发送邮件.

masonryMailbox : Signal.Mailbox String
masonryMailbox =
  Signal.mailbox ""

port masonryCommands : Signal String
port masonryCommands =
  masonryMailbox.signal
Run Code Online (Sandbox Code Playgroud)

由于您正在使用StartApp,您可以返回Effects您的update函数,所以让我们创建一个函数,它将从StartApp初始化程序和update函数内部向此邮箱发送消息.

sendMasonryCommand : String -> Effects.Effects Action
sendMasonryCommand cmd =
  let
    task =
      Signal.send masonryMailbox.address cmd
        `Task.andThen` \_ -> Task.succeed NoOp
  in
    Effects.task task
Run Code Online (Sandbox Code Playgroud)

你可以"initialize"StartAppinit函数中发送命令,如下所示:

init =
  (initialModel, sendMasonryCommand "initialize")
Run Code Online (Sandbox Code Playgroud)

update函数中,如果我们有一个RemoveImage String动作,我们可以向"imageRemove"javascript 发送命令:

update action model =
  case action of
    NoOp ->
      (model, Effects.none)
    RemoveImage url ->
      let model' =
        { model
        | images = List.filter ((/=) url) model.images
        , message = "Removing image " ++ url
        }
      in (model', sendMasonryCommand "imageRemoved")
Run Code Online (Sandbox Code Playgroud)

现在我们需要连接javascript方面来监听这些事件.如果javascript获得命令"initialize",那么我们可以连接砌体.如果我们得到"imageRemoved"命令,我们可以告诉砌体再次触发布局命令.

var app = Elm.fullscreen(Elm.Main);
app.ports.masonryCommands.subscribe(function(cmd) {
  var $grid = $('.grid')

  if (cmd === "initialize") {
    $grid.masonry({
      itemSelector: '.grid-item',
      percentPosition: true,
      columnWidth: '.grid-sizer'
    });

    $grid.imagesLoaded().progress( function() {
      $grid.masonry();
    });  
  } else if (cmd === "imageRemoved") {
    $grid.masonry();
  }
});
Run Code Online (Sandbox Code Playgroud)

我们还可以连接端口以将事件发送回Elm.让我们通过每次砌体完成渲染时向Elm发送消息来添加示例.首先,我们将创建一个名为的端口setMessage.

port setMessage : Signal String
Run Code Online (Sandbox Code Playgroud)

由于这是JavaScript的将出版的端口,我们只定义在榆树函数签名,而不是函数本身.相反,当我们调用时,我们必须从javascript端给出信号初始值Elm.fullscreen().javascript更改为:

var app = Elm.fullscreen(Elm.Main, { setMessage: "" });
Run Code Online (Sandbox Code Playgroud)

现在,在处理"initialize"命令的javascript块内,您可以连接砌体的layoutComplete函数以向此新端口发送消息.

$grid.on("layoutComplete", function() {
  app.ports.setMessage.send("Masonry layout complete!");
});
Run Code Online (Sandbox Code Playgroud)

为了从setMessageElm中的端口使用这些消息,您需要一个SetMessage String动作,并且您需要在StartApp inputs列表中映射信号.您的StartApp初始化代码如下所示:

app =
  StartApp.start
    { init = init
    , view = view
    , update = update
    , inputs = [ Signal.map SetMessage setMessage ]
    }
Run Code Online (Sandbox Code Playgroud)

我在几个要点中提供了所有这些的完整工作示例.这是一个包含榆树代码要点,这里是一个包含html和javascript要点.