Метеор - автоматическое обновление холста с подписанными данными?

Мне может быть что-то не хватает, но кажется, что "волшебство" Метеор вращается вокруг привязки данных к элементам DOM и обновляет фрагменты текста и HTML через дескрипторы: http://docs.meteor.com/#reactivity

Это замечательно, однако, когда вы пытаетесь написать приложение метеорита, которое отображает данные в реальном времени на <canvas> элемент, я не могу понять "метеорный путь" для обновления моего холста, когда текущие данные изменяются, поскольку полотно заполняется с помощью JS-кода, например:

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

а не текст с поддержкой данных в шаблоне HTML.

Я пытаюсь использовать холст, используя данные из Meteor.Collection.

Моя единственная мысль заключалась в том, чтобы внедрить JS-код canvas-рисунка в шаблон HTML в теге script, заполненном символами руля, но это кажется неправильным, поскольку события meteor и код привязки данных уже являются клиентской JS.

Есть ли способ прослушивания живых изменений данных, который запускает рисование на холсте через JS вместо HTML-элементов/текста?

Пожалуйста, дайте мне знать, если я каким-то образом проясню вопрос.

Update: Том ответил ниже, заметив Meteor.deps, которые хотят выполнить произвольный код в реактивном контексте: http://docs.meteor.com/#on_invalidate

Я попробую это и обновит здесь, если это сработает.

Ответ 1

Это работает:

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()
  })
}

Ответ 2

Возможно, ответ на ваш вопрос - использовать 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
})

Ответ 3

У меня возникли проблемы с обновлением холста, поэтому я создал эту простую игровую демонстрацию: https://github.com/randompast/Meteor-SimpleGame