2016-05-10 2 views
2

Новое в Ractive.js, и после прочтения документов я все еще зависаю на некоторых синтаксисах. В приведенном ниже примере создается тег canvas для каждого элемента в моем массиве, а затем создается объект , отличный от объект пользовательского класса, для каждого из которых обрабатывается анимация. Как отмечено в комментариях, я бросаю три ошибки.Ссылаясь на свойства Child в Ractive.js

В обработчике событий я хочу ссылаться на свойство height (определенное в моем массиве), но ни this.get (repeatater.height), ни this.repeater.height работают. Я также хочу вызвать метод объекта, связанного с этим событием, но использование этого.myCustomClass.setFrame() также не работает.

Я получаю хотя бы одну ошибку в коде для моего класса анимации, когда пытаюсь обратиться к методам canvas: this.canvas.getContext() где «холст» - это идентификатор, который я передал в конструктор объекта.

Так ясно, что я неправильно понимаю, как обращаться к дочерним свойствам активных объектов. Любая помощь здесь?

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

ответ

0

Я думаю, что вам не хватает является добавление массива объектов CanvasSprite данных теля Тягового, а затем с помощью контекста событий, чтобы получить текущий спрайт (см https://jsfiddle.net/martypdx/srbvekc4/2/ для полного примера):

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: Вы также можете использовать компоненты, чтобы лучше инкапсулировать каждый спрайт (см 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 } 
}); 

ОБНОВЛЕНО: используйте многопараметрический конструктор, а также реализован лучший инкапсулирование, если компонент обрабатывает экземпляр CanvasSprite.

+0

Спасибо за ответ. Это гораздо более элегантное решение, и я вижу свою проблему с точки зрения добавления моих объектов в Ractive data. Кроме ... вы изменили конструктор, чтобы взять массив, и это не вариант для меня здесь, так как я использую этот код в десятках других проектов. Мой ответ на коленец - это перегрузить конструктор, чтобы взять массив, но я знаю, что не могу этого сделать в Javascript. Любая идея, как это сделать и по-прежнему передавать ему отдельные аргументы? (используя ваш первый пример здесь для краткости, кстати) –

+0

Пробовал что-то вроде этого, но он не работает: 'var canvasSprites = []; canvasSprites.push (this.get ('повторители'). ForEach (функция (повторитель) { новый CanvasSprite (повторитель.ид, ретранслятор, ретранслятор.хэйт, повторитель.spriteSheetURL, повторитель.красы, повторители.столбцы, ретранслятор .totalFrames); })); this.set ({canvasSprites}); ' –

+0

О, вы можете изменить конструктор так, как хотите. В этом примере это объект, а не массив. Я обновлю пример, как вы его получили, и будет ли он более понятным для вас без синтаксиса ES2015? – martypdx