Threepenny GUI - 使用带有 canvas 的接收器

Threepenny GUI - Using sink with a canvas

我正在学习如何使用 Threepenny GUI,我已从 canvas 连接到点击事件流,将该事件流映射到 Point 流并应用 accumB[] 然后 Event Point 得到 Behaviour [Point]

其中 Point:

data Point = Point {
  x :: Int,
  y :: Int
}

以及将点击 Event 流映射到 Behaviour [Point] 的代码:

let pointStream = uncurry Point <$> UI.mousedown canvas

let pointsStream = fmap (:) pointStream

let pointsAccumB = accumB [] pointsStream

pointsBehaviour <- pointsAccumB

然后我想将这些点绘制到 canvas 元素,我已将其添加到 setup 方法中 HTML 的正文中。

我已经设法从这样的行为中得出要点:

on UI.click drawButton $ const $ do
  UI.clearCanvas canvas

  points <- currentValue pointsBehaviour

  -- Draw the points here

但问题是我希望每次用户单击 canvas 时都将点绘制到 canvas,而不需要用户去单击按钮。或者,换句话说,我想在点流中组合一个绘制点函数。

根据我的研究,看起来 sink 可能是我需要用来将 FRP 样式中的 UI 的行为和突变联系在一起的函数。

但是,我很难理解如何将它们拼凑起来(即 sink 应用程序对于这个给定的用例会是什么样子?)。目前甚至可以用 Threepenny 做到这一点吗?

将您的点绘图代码包装在 WriteAttr 中并将其传递给 sink。该属性可能定义如下:

drawnPoints :: WriteAttr Canvas [Point]
drawnPoints = mkWriteAttr $ \canvas point -> do
  UI.clearCanvas canvas
  -- Draw the points here

然后您可以使用 sink:

连接您的实际点和 canvas
element canvas # sink drawnPoints pointsBehaviour