2016-05-10 8 views
2

Neu inRactive.js und nach dem Lesen der Dokumente Ich bin immer noch auf etwas von der Syntax hängen. Mein Beispiel unten erstellt ein Canvas-Tag für jedes Element in meinem Array und instanziiert dann ein distinct Objekt einer benutzerdefinierten Klasse für jedes, um die Animation zu behandeln. Wie in den Kommentaren erwähnt, werfe ich drei Fehler.Unter Child-Eigenschaften inRactive.js

Im Event-Handler möchte ich auf die Eigenschaft height verweisen (definiert in meinem Array), aber weder this.get (repeater.height) noch this.repeater.height funktionieren. Ich möchte auch eine Methode des Objekts aufrufen, die diesem Ereignis zugeordnet ist, aber die Verwendung von this.myCustomClass.setFrame() funktioniert auch nicht.

Ich bekomme auch mindestens einen Fehler im Code für meine Animationsklasse, wenn ich versuche, auf Methoden der Zeichenfläche zu verweisen: this.canvas.getContext() wo "Leinwand" ist die ID, die ich in der übergeben Objektkonstruktor.

Also klar verstehe ich etwas darüber, wie man auf Kind Eigenschaften von ractive Instanzen beziehen. Irgendwelche Hilfe hier?

var repeater = [ 
    {id: "stalkerOne", width: 225, height: 432, left: 8, spriteSheetURL: "spriteSheets/stalkerone.jpg", rows: 5, columns: 5, totalFrames: 24}, 
    {id: "stalkerTwo", width: 175, height: 432, left: 230, spriteSheetURL: "spriteSheets/stalkertwo.jpg", rows: 6, columns: 5, totalFrames: 26}, 
    {id: "stalkerThree", width: 251, height: 432, left: 404, spriteSheetURL: "spriteSheets/stalkerthree.jpg", rows: 6, columns: 5, totalFrames: 28} 
] 

var CanvasAnimation = Ractive.extend({ 
    oninit: function() { 
     this.get('repeaters').forEach(function(repeater){ 
      var myCanvasSprite = new CanvasSprite(repeater.id, repeater.width, repeater.height, repeater.spriteSheetURL, repeater.rows, repeater.columns, repeater.totalFrames); 
      myCanvasSprite.setFrame(0); 
      //this.canvas.getContext() throwing error in class code 
     }); 

     this.on('setFrame', function (event) { 
      var offsetY = event.original.clientY - event.node.getBoundingClientRect().top; 
      var relY = offsetY/this.get(repeater.height); //why doesn't this.get() work here? 
      this.myCanvasSprite.setFrame(relY); //custom class method not working either... 
     }); 
    } 
});  

var canvasAnimation = new CanvasAnimation({ 
    el: '#container', 
    template: '#template', 
    data: { repeaters: repeater } 
}); 

Antwort

0

denke ich, was Sie fehlt, ist das Array von CanvasSprite Objekte zu den Ractive Daten hinzufügen und dann den Ereigniskontext unter Verwendung der aktuellen Sprite zu erhalten (https://jsfiddle.net/martypdx/srbvekc4/2/ für volle Beispiel):

var CanvasAnimation = Ractive.extend({ 
    template: ` 
     {{#each sprites}} 
      <li on-click='setFrame'>{{.id}}</li> 
     {{/each}}`, 
    oninit() { 
     var sprites = this.get('repeaters').map(function(repeater){  
      return new CanvasSprite(repeater.id, repeater.width, repeater.height, repeater.spriteSheetURL, repeater.rows, repeater.columns, repeater.totalFrames); 
     }); 

     // add the class instances to the data 
     this.set('sprites', sprites); 

     this.on('setFrame', function (event) { 
      // here's how we get the sprite from the event 
      var sprite = event.context; 
      var offsetY = event.original.clientY - event.node.getBoundingClientRect().top; 
      var relY = offsetY/sprite.height; 
      sprite.setFrame(relY); 
     }); 
    }, 
    onrender() { 
     // wait till render, otherwise nothing there! 
     this.get('sprites').forEach(sprite => sprite.setFrame(0)); 
    } 
}); 

EDIT: Sie auch Komponenten verwenden können, um besser jeden Sprit zu kapseln (siehe https://jsfiddle.net/martypdx/srbvekc4/1/):

var CanvasAnimation = Ractive.extend({ 
    template: ` 
     {{#each repeater}} 
      <Sprite options='{{this}}'></Sprite> 
     {{/each}}` 
});  

var Sprite = Ractive.extend({ 
    template: `<li on-click='setFrame'>{{sprite.id}}</li>`, 
    oninit() { 
     const sprite = new CanvasSprite(repeater.id, repeater.width, repeater.height, repeater.spriteSheetURL, repeater.rows, repeater.columns, repeater.totalFrames); 

     // since example template is using properties from sprite, 
     // we add it to the data 
     this.set('sprite', sprite); 

     this.on('setFrame', function (event) { 
      var offsetY = event.original.clientY - event.node.getBoundingClientRect().top; 
      var relY = offsetY/sprite.height; 
      sprite.setFrame(relY); 
     }); 
    }, 
    onrender() { 
     this.sprite.setFrame(0); 
    } 
}); 

var canvasAnimation = new CanvasAnimation({ 
    el: document.body, 
    template: '#template', 
    data: { repeaters: repeater }, 
    components: { Sprite } 
}); 

AKTUALISIERT: Verwenden Sie einen Konstruktor mit mehreren Parametern und haben Sie auch eine bessere Kapselung erreicht, wenn die Komponente die Instanziierung von CanvasSprite handhabt.

+0

Danke für die Beantwortung. Das ist eine viel elegantere Lösung, und ich sehe mein Problem darin, meine Objekte zu den reaktiven Daten hinzuzufügen. Außer ... Sie haben den Konstruktor geändert, um ein Array zu erstellen, und das ist für mich keine Option, da ich diesen Code in Dutzenden anderer Projekte verwende. Meine kniejerk Antwort ist, den Konstruktor zu überladen, um ein Array zu nehmen, aber ich weiß, dass ich das in Javascript nicht tun kann. Irgendeine Idee wie man das macht und trotzdem einzelne Argumente weitergibt? (Verwenden Sie Ihr erstes Beispiel hier für die Kürze, btw) –

+0

Versucht so etwas, aber es funktioniert nicht: 'var canvasSprites = []; canvasSprites.push (this.get ('Repeater'). ForEach (Funktion (Repeater)) { neue CanvasSprite (Repeater.id, Repeater.width, Repeater.Height, Repeater.SpriteSheetURL, Repeater.Rows, Repeater.Spalten, Repeater .totalFrames); })); this.set ({canvasSprites}); ' –

+0

Oh, Sie können den Konstruktor beliebig ändern. In diesem Beispiel ist es ein Objekt, kein Array. Ich werde das Beispiel so aktualisieren, wie Sie es hatten, und wäre es für Sie ohne die ES2015-Syntax klarer? – martypdx

Verwandte Themen