2012-05-29 13 views
11

I może być czegoś brakuje, ale wydaje się, że Meteor jest „magia” kręci się wokół wiązania danych do elementów DOM i aktualizacja tekstu i fragmenty HTML za pośrednictwem kierownicy: http://docs.meteor.com/#reactivityMeteor - automatyczne aktualizowanie kanwy z subskrybowanymi danymi?

To jest wielki, jednak, kiedy próbuje pisać aplikacja meteor, który wyświetla dane żyć w < płótnie > elementu, nie mogę dowiedzieć się „meteor drogę”, aby zaktualizować moje płótno gdy żywe zmiany danych, ponieważ płótno jest wypełniana za pomocą kodu JS jak:

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

a nie tekst oparty na danych w szablonie HTML.

Próbuję narysować na płótnie przy użyciu danych z Meteor.Collection.

Moja jedyna myśl polegała na umieszczeniu kodu JS na rysunku w szablonie HTML w znaczniku skryptu zapełnionym przez wariacje kierownicy, ale wydaje się to błędne, ponieważ zdarzenia meteorytów i kod wiążący dane to już JS po stronie klienta.

Czy jest jakiś sposób nasłuchiwania zmian danych na żywo, które powodują rysowanie na płótnie przez JS zamiast elementów HTML/tekstu?

Proszę dać mi znać, jeśli mogę wyjaśnić kwestię w jakiś sposób

Aktualizacja: poniżej Toma odpowiedź mnie zauważy Meteor.deps, które wyglądają, aby umożliwić wykonanie dowolnego kodu w kontekście reaktywnego: http://docs.meteor.com/#on_invalidate

Wypróbuję to i zaktualizuję tutaj, jeśli zadziała.

+0

I Nie jestem pewien, czy to właśnie masz na myśli przez "osadzone ... w tagu skryptu". Obecnie robię coś w rodzaju umieszczania {{drawCanvas}} w szablonie zawierającym moje płótno, i robię cały rysunek wewnątrz funkcji, która jest częścią Template.canvas.helper o nazwie "drawCanvas", ta funkcja nic nie zwraca, więc nic nie dostaje renderowane, ale jest wykonywane, aby zaktualizować płótno. Czy to już próbowałeś? Template.name.helper jest automatycznie reaktywny, tak długo, jak długo zależy od ReactiveDict lub jakiegoś modelu, który będzie aktualizowany zgodnie ze zmianami. –

+0

Co mam na myśli przez ten komentarz, to dynamiczne generowanie kodu JS jako ciągu w szablonie (który jest oczywiście dziwaczne). Moja odpowiedź poniżej wydawała się być "poprawnym" sposobem z Meteorem – 7zark7

+0

, który jest rzeczywiście absurdalny! Ale czy moja metoda wygląda dobrze? Pomysł polega właśnie na użyciu niewidzialnego {{drawCanvas}}, które nie robi nic, co zostaje ponownie uruchomione za każdym razem, gdy zmieniają się niektóre reaktywne dane (tym samym ponownie rysując płótno). –

Odpowiedz

5

To działa:

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

To działa - dzięki! Chociaż osobiście tego szukam, należy wykonać pełne odświeżanie tylko przy starcie - a następnie wykonywać tylko przyrostowe odświeżanie w trakcie aktualizacji/dodawania/usuwania. Czy robisz to w odpowiedni sposób tylko podczas uruchamiania/renderowania, a nie po każdej aktualizacji? Jeśli wstawisz kwerendy do szablonu template.render, to nie działa. – semateos

+1

Powodem pełnego przerysowania jest to, że płótno nie obsługuje usuwania/aktualizowania poszczególnych kształtów. AFAIK, musisz przerysować całe płótno, jeśli kształty zachodzą na siebie, itp. – 7zark7

+0

@semateos Możesz to osiągnąć, używając biblioteki takiej jak Pixi.js, która naśladuje listę wyświetlania Flash. –

7

Być może odpowiedzią na twoje pytanie jest użycie Collection.observe (http://docs.meteor.com/#observe) i wywołanie odpowiedniego kodu przerysowania w różnych wywołaniach zwrotnych.

Na przykład coś takiego:

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

Dzięki kolego, tego nie widziałem.Jednym z problemów w moim przypadku jest to, że muszę przerysować całe płótno (np. Usunięcie prostokąta wymaga przerysowania prostokątów poniżej/nad nim), co oznacza, że ​​potrzebuję wyników całego zapytania, a nie tylko dodanych/usuniętych/zmienionych. – 7zark7

+0

Pewnie. Myślę, że to, co masz, jest właściwą drogą. Chciałbym, żeby Meteor miał prostszy sposób na ustawienie kontekstu i rozwiązanie problemu z unieważnieniem. –