2012-05-23 9 views
8

Tworzę aplikację, w której na płótnie malowane są różne prostokąty i próbuję to zrobić za pomocą Trzonu. Mam model o nazwie pole:Tworzenie widoku Backbone.js do rysowania obiektów na płótnie

Box = Backbone.Model.extend({ 
     defaults: { 
      x: 0, 
      y: 0, 
      w: 1, 
      h: 1, 
      color: "#FF9000", 
      linewidth: 3, 
      id: 0, 
     }, 

     drawBox: function(ctx) { 
      ctx.fillStyle = "#FF9000"; 
      ctx.globalAlpha = 0.1; 
      ctx.fillRect(this.get("x"), this.get("y"), this.get("w"), this.get("h")); //transparent box in the back 
      ctx.globalAlpha = 1; 
      ctx.strokeStyle = this.get("color"); 
      ctx.lineWidth = this.get("linewidth"); 
      ctx.strokeRect(this.get("x"), this.get("y"), this.get("w"), this.get("h")); //rectangle on top  
     } 
    }); 

I mam również kolekcję tego modelu nadwozia:

BoxSet = Backbone.Collection.extend({ 
     model: Box   
    }); 

Co mam na myśli, aby mieć widok, w którym można umieścić każdy model Box w kolekcja BoxSet na płótnie za pomocą metody drawBox w modelu Box, ale do tej pory wszystkie tutoriale i przykłady zajmują się prostymi szablonami tekstowymi i nie mogę wymyślić, jak to osiągnąć.

Wszelkie pomysły na temat tego, jak można tego dokonać za pomocą widoków kręgosłupa?

Z góry dziękuję.

Odpowiedz

18

Chciałbym śledzić podział modeli i widoków oferowany przez Backbone. Zachować swoje modele jako repozytorium danych:

var Box = Backbone.Model.extend({ 
    defaults: { 
     x: 0, 
     y: 0, 
     w: 1, 
     h: 1, 
     color: "#FF9000", 
     linewidth: 3 
     // don't define a default id, that leads to strange behaviors 
    } 
}); 

var BoxSet = Backbone.Collection.extend({ 
    model:Box 
}); 

i określić poglądy czynią różne kawałki na płótnie:

var BoxView = Backbone.View.extend({ 
    render: function() { 
     var model = this.model, ctx = this.options.ctx; 

     ctx.fillStyle = "#FF9000"; 
     ctx.globalAlpha = 0.1; 
     ctx.fillRect(
      model.get("x"), model.get("y"), 
      model.get("w"), model.get("h") 
     ); 

     ctx.globalAlpha = 1; 
     ctx.strokeStyle = model.get("color"); 
     ctx.lineWidth = model.get("linewidth"); 
     ctx.strokeRect(
      model.get("x"), model.get("y"), 
      model.get("w"), model.get("h") 
     ); 
    } 
}); 

var SetView= Backbone.View.extend({ 
    initialize: function() { 
     this.listenTo(this.collection, "all", this.render); 
    }, 

    render: function() { 
     var canvas = this.el, ctx = canvas.getContext("2d"); 
     ctx.clearRect(0, 0, canvas.width, canvas.height); 

     this.collection.each(function(model) { 
      var view = new BoxView({ctx: ctx, model: model}); 
      view.render(); 
     }) 
    } 
}); 

I wreszcie instancji i render:

var c = new BoxSet(); 
c.add({x: 150, y: 150, w: 100, h: 100}); 
c.add({x: 10, y: 10, w: 100, h: 100}); 

var v = new SetView({ 
    el: $("canvas"), 
    collection : c 
}); 
v.render(); 

A skrzypce zobacz te dwa ładne kwadraty http://jsfiddle.net/JB9yg/

Kolejny, w którym zmiana t Kolekcja ta prowadzi do ponownego renderowania: http://jsfiddle.net/JB9yg/1/

Ten przykład może być zbudowany na podstawie czystszych operacji, ale to powinno zacząć.

+0

Dzięki @nikoshr, jest doskonałym rozwiązaniem. Daje mi to większą kontrolę nad kwadratami i sprawia, że ​​bardziej elastyczne jest wprowadzanie dalszych modyfikacji. – rpabon

+0

Jakieś pomysły, w jaki sposób SetView może malować lub usuwać pudełka z płótna za każdym razem, gdy ktoś je dodaje/usuwa z kolekcji? – rpabon

+1

@rpabon Dodałem możliwe rozwiązanie, w którym wszystko zostanie przerysowane. Interesujące może być sprawdzenie, czy zestaw instrukcji można zdefiniować jako obiekt i manipulować niezależnie na płótnie. – nikoshr

2

Możesz również spróbować użyć wtyczki Backbone.KineticView, aby dodać obsługę kanwy do Szkieletu. Działa za pośrednictwem KineticJS, więc może również wykorzystać całą moc delegowania zdarzeń dla węzłów canvas.

przykład:

var MyView = Backbone.KineticView.extend({ 
    // build Kineticjs object, then return it. 
    el : function(){ 
    var rect = new Kinetic.Rect({ 
     x : 100, 
     y : 100, 
     width : 50, 
     height : 50, 
     fill : 'green', 
     id : 'rect' 
    }); 
    var circle = new Kinetic.Circle({ 
     x : 200, 
     y : 100, 
     radius : 50, 
     fill : 'red', 
     name : 'circle' 
    }); 
    var group = new Kinetic.Group(); 
    group.add(rect).add(circle); 
    return group; 
    }, 
    // setup events 
    events : { 
    'click #rect' : function(){ 
     console.log("on rectangle clicked"); 
    }, 
    'mouseover .circle' : 'onMouseOverCircle' 
    }, 
    onMouseOverCircle : function(){ 
    console.log('Mouse is over circle'); 
    }, 
    render : function(){ 
    // this.$el - cached kineticjs object. 
    this.options.layer.add(this.$el); 
    layer.draw(); 
    } 
}); 

var stage = new Kinetic.Stage({ 
    container : 'container', 
    width : 300, 
    height : 300 
}); 
var layer = new Kinetic.Layer(); 
stage.add(layer); 

view = new MyView({layer:layer}); 
view.render(); 
Powiązane problemy