2013-03-14 3 views
6

J'ai une classe simple que j'utilise pour gérer des scènes dans three.js. J'ai des problèmes avec la boucle requestAnimationFrame trouvant la référence de la fonction. Je sais qu'il me manque quelque chose de fondamental ici, piégé dans certains ce cauchemar. Dois-je utiliser bind ou call pour transmettre la référence this à requestAnimationFrame?Appel récursif dans la classe Javascript (requestanimationframe)

var THREE = THREE || {}; 
var SceneBuddy = SceneBuddy || {}; 

SceneBuddy = function(scene, camera) { 
    this.scene = scene; 
    this.camera = camera; 
    this.sceneClock = new THREE.Clock(); 
    this.renderer = {}; 
    this.resolution = {}; 
    this.controls = {}; 
}; 
//Start Animate 
SceneBuddy.prototype.startAnimate = function() { 
    requestAnimationFrame(this.startAnimate); //this does not work, type error 
    this.render.call(this); 
}; 
//Render Function 
SceneBuddy.prototype.render = function() { 
    var delta = this.sceneClock.getDelta(); 
    this.controls.update(delta); 
    this.renderer.render(this.scene,this.camera); 
}; 

//Setup Renderer 
SceneBuddy.prototype.initRenderer = function(resolution) { 
    if (!Detector.webgl) { 
     Detector.addGetWebGLMessage(); 
     return; 
    } 
    else { 
     var renderer = new THREE.WebGLRenderer({ 
      antialias: true, 
      preserveDrawingBuffer: true 
     }); 
     renderer.setSize(resolution.x, resolution.y); 
     renderer.shadowMapEnabled = true; 
     this.resolution = resolution; 
     this.renderer = renderer; 
    } 
}; 

J'utilise actuellement l'utilisation SceneBuddy comme ceci:

var camera = new THREE.PerspectiveCamera(75, SCREEN_WIDTH/SCREEN_HEIGHT, 1, 100000); 
    var scene = new THREE.Scene(); 
    var sceneBuddy = new SceneBuddy(scene, camera); 
    sceneBuddy.initRenderer({x: 940, y: 400}); 
    sceneBuddy.attachRenderer(container); //attaches renderer to dom element 
    sceneBuddy.initControls(); 
    sceneBuddy.startAnimate(); // broken. 
+0

Comment êtes-vous instancier SceneBuddy? – bfavaretto

+0

Pourriez-vous ajouter le code complet de la définition de la fonction 'requestAnimationFrame' sur l'objet global? Aussi: Je m'attendrais à ce que la fonction 'startAnimate' accepte un paramètre timestamp –

+0

requestAnimationFrame est fourni par le shim inclus avec three.js. Vous n'êtes pas sûr de suivre votre suggestion concernant la fourniture d'un horodatage? – mhilmi

Répondre

11

Utilisez bind lors du passage d'une fonction permettant de spécifier ce que this sera quand la fonction est appelée:

SceneBuddy.prototype.startAnimate = function() { 
    requestAnimationFrame(this.startAnimate.bind(this)); 
    this.render(); 
}; 
+0

Cela fonctionne, merci. Par curiosité, quelque chose comme ceci est nécessaire: this.render.call (this); ou est-ce redondant? Précédemment this.render() ne fonctionnait pas à moins que j'ai appelé comme ci-dessus, une fois dans la fonction de rendu, le ce contexte n'a pas été défini. Pourrait avoir juste été un petit problème de la rupture de requestAnimationFrame. – mhilmi

+0

Je ne peux pas penser à un exemple où 'this.render.call (this)' fonctionnerait quand 'this.render()' ne le fait pas - ils font la même chose. Si vous ne liez pas le rappel rAF alors 'this' sera l'objet global/fenêtre qui n'a probablement pas de fonction' render' – Dennis