TrueWheel
TrueWheel

Reputation: 987

backbone.js - Having multiple instances of the same view

I am having problems having multiple instances in of the same view in different div elements. When I try to initialize them only the second of the two elements appear no matter what order I put them in.

Here is the code for my view.

  var BodyShapeView = Backbone.View.extend({
    thingiview: null,
    scene: null,
    renderer: null,
    model: null,
    mouseX: 0,
    mouseY: 0,

events:{
  'click button#front' : 'front',
  'click button#diag' : 'diag',
  'click button#in' : 'zoomIn',
  'click button#out' : 'zoomOut',
  'click button#on' : 'rotateOn',
  'click button#off' : 'rotateOff',
  'click button#wireframeOn' : 'wireOn',
  'click button#wireframeOff' : 'wireOff',
  'click button#distance' : 'dijkstra'
},

initialize: function(name){
  _.bindAll(this, 'render', 'animate');

     scene = new THREE.Scene();
     camera = new THREE.PerspectiveCamera( 15, 400 / 700, 1, 4000 );
     camera.position.z = 3;
     scene.add( camera );
     camera.position.y = -5;

     var ambient = new THREE.AmbientLight(  0x202020 );
     scene.add( ambient );

     var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.75 );
     directionalLight.position.set( 0, 0, 1 );
     scene.add( directionalLight );


     var pointLight = new THREE.PointLight( 0xffffff, 5, 29 );
     pointLight.position.set( 0, -25, 10 );
             scene.add( pointLight );

     var loader = new THREE.OBJLoader();
     loader.load( "img/originalMeanModel.obj", function ( object ) {

        object.children[0].geometry.computeFaceNormals();
        var  geometry = object.children[0].geometry;
                console.log(geometry);
        THREE.GeometryUtils.center(geometry);
        geometry.dynamic = true;
        var material = new THREE.MeshLambertMaterial({color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors });
        mesh = new THREE.Mesh(geometry, material);
        model = mesh;
        // model = object;
        scene.add( model );
     } );

     // RENDERER
     renderer = new THREE.WebGLRenderer();
     renderer.setSize( 400, 700 );
     $(this.el).find('.obj').append( renderer.domElement );

    this.animate();

},

Here is how I create the instances

var morphableBody = new BodyShapeView({ el: $("#morphable-body") });

  var bodyShapeView = new BodyShapeView({ el: $("#mean-body") });

Any help would be really appreciated.

Thanks in advance.

Upvotes: 1

Views: 1417

Answers (2)

nikoshr
nikoshr

Reputation: 33364

In your initializemethod, you access global variables instead of instance variables: scene = new THREE.Scene(); will in fact reference window.scene.

Check this example

var BodyShapeView = Backbone.View.extend({
    scene:null,
    initialize:function(opts) {
        scene=opts.scene;
    }
});

var s1=new BodyShapeView({scene:'s1'});
var s2=new BodyShapeView({scene:'s2'});

console.log(window.scene);  //outputs s2
console.log(s1.scene); //outputs null

http://jsfiddle.net/K8tjJ/1/

Change these references to this.scene, this.camera, etc.

var BodyShapeView = Backbone.View.extend({
    scene:null,
    initialize:function(opts) {
        this.scene=opts.scene;
    }
});

var s1=new BodyShapeView({scene:'s1'});
var s2=new BodyShapeView({scene:'s2'});

console.log(window.scene); //outputs undefined
console.log(s1.scene); //outputs s1

http://jsfiddle.net/K8tjJ/2/

Additionally, loader.load uses a callback to process its results, you will (probably) lose the reference to this in the function. Try

var _this=this;
loader.load( "img/originalMeanModel.obj", function ( object ) {
...
_this.scene.add( _this.mesh ); // or _this.model if you prefer, but beware

});

Note that this.model is a special variable in Backbone.View and should be treated with care if you ever want to pass a model to your view.

Upvotes: 1

jackwanders
jackwanders

Reputation: 16050

The el attribute only needs a jQuery style selector string. Try:

var morphableBody = new BodyShapeView({ el: "#morphable-body" });
var bodyShapeView = new BodyShapeView({ el: "#mean-body" });

UPDATE

Also, your problem may be that you're not using the this keyword when defining scene, camera, and renderer. It could be that the second view is overwriting the first view as a result. Try:

this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera( 15, 400 / 700, 1, 4000 );

...

// RENDERER
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize( 400, 700 );
$(this.el).find('.obj').append( this.renderer.domElement );

Upvotes: 1

Related Questions