【问题标题】:Meteor - automatically updating canvas with subscribed data?Meteor - 使用订阅数据自动更新画布?
【发布时间】:2014-12-01 00:00:32
【问题描述】:

我可能遗漏了一些东西,但 Meteor 的“魔法”似乎围绕着将数据绑定到 DOM 元素,以及通过把手更新文本和 HTML 片段:http://docs.meteor.com/#reactivity

这很好,然而,当尝试编写一个在 元素中显示实时数据的流星应用程序时,我无法弄清楚在实时更新我的​​画布时的“流星方式”数据更改,因为画布是通过 JS 代码填充的,例如:

var g = canvas.getContext('2d')
g.fillRect(x, y, w, h)

而不是 HTML 模板中的数据支持文本。

我正在尝试使用 Meteor.Collection 中的数据在画布上绘图。

我唯一的想法是将画布绘图 JS 代码嵌入 HTML 模板中的一个由把手变量填充的脚本标记中,但这似乎是错误的,因为流星的事件和数据绑定代码已经是客户端 JS。

有什么方法可以监听实时数据变化,通过 JS 而不是 HTML 元素/文本触发在画布上绘图?

如果我能以某种方式澄清问题,请告诉我

更新: 下面汤姆的回答让我注意到 Meteor.deps,它看起来允许在反应式上下文中执行任意代码: http://docs.meteor.com/#on_invalidate

如果可行,我会尝试并在此处更新。

【问题讨论】:

  • 我不确定这是否是您所说的“嵌入...在脚本标签中”的意思。目前我正在做一些事情,比如将 {{drawCanvas}} 放在包含我的画布的模板中,并在名为“drawCanvas”的 Template.canvas.helper 的一部分的函数内进行所有绘图,此函数不返回任何内容,因此不会渲染任何内容,但它会被执行,因此它将更新画布。那是你已经尝试过的吗? Template.name.helper 是自动响应的,只要它依赖于 ReactiveDict 或某个模型,它就会在更改时相应更新
  • 我的意思是在模板中动态生成 JS 代码作为字符串(这显然很奇怪)。我在下面的回答似乎是 Meteor 的“正确”方式
  • 这真是荒谬!但是我的方法看起来好吗?这个想法只是使用一个不可见的 {{drawCanvas}},它什么都不做,只要一些反应性数据发生变化(从而重新绘制画布),它就会重新运行
  • 这听起来像是一个聪明的解决方案!可能想要比较方法之间的性能并报告。

标签: meteor


【解决方案1】:

也许你的问题的答案是使用Collection.observe (http://docs.meteor.com/#observe) 并在各种回调中触发相关的重绘代码。

例如:

Rectangles.observe({
  added: function(rect) {
    var g = canvas.getContext('2d');
    g.fillRect(rect.x, rect.y, rect.w, rect.h);
  },
  // etc
})

【讨论】:

  • 谢谢伙计,没看到。在我的特殊情况下,一个问题是我需要重绘整个画布(例如,删除一个矩形需要在其下方/上方重绘矩形),这意味着我需要整个查询结果,而不仅仅是添加/删除/更改。
  • 当然。我想你所拥有的是正确的方法。我希望 Meteor 有一种更简单的方法来设置上下文 + 顺便处理失效。
【解决方案2】:

这行得通:

var Shapes = new Meteor.Collection('shapes')

if (Meteor.is_client) {
  // Function that redraws the entire canvas from shapes in Meteor.Collection
  function drawShapes() {
    var shapes = Shapes.find({})
    shapes.forEach(function(shape) {
      // draw each on canvas
    })
  }

  var startUpdateListener = function() {
    // Function called each time 'Shapes' is updated.
    var redrawCanvas = function() {
      var context = new Meteor.deps.Context()
      context.on_invalidate(redrawCanvas) // Ensures this is recalled for each update
      context.run(function() {
        drawShapes()
      })
    }
    redrawCanvas()
  }

  Meteor.startup(function() {
    startUpdateListener()
  })
}

【讨论】:

  • 这确实有效 - 谢谢!虽然我个人正在寻找的是仅在启动时进行完全重绘 - 然后只在更新/添加/删除时进行增量重绘。您是否仅在启动/渲染时而不是在每次更新后才做这种事情的正确方法?如果您将查询放在 template.rendered 中,它似乎不起作用。
  • 我完全重绘的原因是 Canvas 不支持删除/更新单个形状。 AFAIK,如果形状重叠等,您必须重绘整个画布。
  • @semateos 您可以使用 Pixi.js 之类的库来实现该行为,该库模仿 Flash 显示列表。
【解决方案3】:

我在更新画布时遇到了一些问题,所以我创建了这个简单的游戏演示: https://github.com/randompast/Meteor-SimpleGame

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 2014-01-09
    相关资源
    最近更新 更多