2016-11-07 41 views
0

好吧..對於JS和three.js來說這麼新,我很好奇爲什麼我在函數自我調用中獲得堆棧超出, three.js自然地調用每個設計。然而,只有當我從主功能中刪除呼叫時纔會發生。three.js未捕獲的RangeError:渲染循環中超出的最大調用堆棧大小

我已經基本上採用了 three.js-Documentation的立方體示例,我試圖設置動畫,以便動態添加和減去場景中的對象以及將其發送到特定的畫布。從three.js所

 var scene = new THREE.Scene(); 
     var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 

     var renderer = new THREE.WebGLRenderer(); 
     renderer.setSize(window.innerWidth, window.innerHeight); 
     document.body.appendChild(renderer.domElement); 

     var geometry = new THREE.BoxGeometry(1, 1, 1); 
     var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); 
     var cube = new THREE.Mesh(geometry, material); 
     scene.add(cube); 

     camera.position.z = 5; 

     var render = function() { 
      requestAnimationFrame(render); 

      cube.rotation.x += 0.1; 
      cube.rotation.y += 0.1; 

      renderer.render(scene, camera); 
     }; 

     render(); 

上的動畫調用render();聚焦

原始代碼被稱爲reqestAnimationFrame()功能的自我。爲了打破以備將來使用的程序結構,我將它設置了像這樣(在後視線不是最好的選擇):

function e3Dview(){ 
    // Set the e Canvas 
    this.canvas = document.getElementById("eplot3D") 

    scene = new THREE.Scene(); 
    camera = new THREE.PerspectiveCamera(75, this.canvas.width/this.canvas.height, 0.1, 1000); 

    renderer = new THREE.WebGLRenderer({ canvas: eplot3D }); 
    renderer.setSize(this.canvas.width, this.canvas.height); 

    var geo = new THREE.BoxGeometry(1, 1, 1); 
    var mat = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); 
    mat.wireframe = true 
    this.cube = new THREE.Mesh(geo, mat); 
    scene.add(this.cube); 

    camera.position.z = 5; 

    controls = new THREE.OrbitControls(camera, renderer.domElement); 

    // Execute render 
    this.renderloop(); 

}; 

e3Dview.prototype.renderloop = function(){ 
    requestAnimationFrame(this.renderloop()); 

    this.cube.rotation.x += 0.01; 
    this.cube.rotation.y += 0.01; 

    renderer.render(scene, camera); 

}; 

e3Dview.prototype.sceneClear = function(){ 
    scene.children.forEach(function(object){ 
     scene.remove(object); 
    }); 
}; 

一旦我移動渲染循環的inital父外呼,我得到一個「計算器」錯誤....

未捕獲的RangeError:最大調用堆棧大小超過

所以我的問題是怎麼回事,當在requestAnimationFrame沒關係,但是當同樣的事情發生外渲染調用本身父母叫s大頭釘未被清除並且失敗?

我錯過了什麼?

回答

3

的問題是這一行:

requestAnimationFrame(this.renderloop()); 

這裏您可以有效調用renderloop()立即,而不是傳遞函數爲回調requestAnimationFrame,從而導致無限遞歸循環。

當然人們可能會嘗試將其更改爲以下,但這樣做也不行,因爲傳遞函數原型未綁定任何對象:

requestAnimationFrame(this.renderloop); // This won't work, either. 

這裏的一個解決方案是結合所述函數應用於所述對象的範圍:

requestAnimationFrame(this.renderloop.bind(this)); // This will work, but overhead at 60FPS might not be worth it 

我建議移動renderloop功能到e3Dview構造爲私有方法,像這樣:

function e3Dview(){ 
    var $this = this; // Hold the current object's scope, for accessing properties from within the callback method. 

    ... 

    function renderloop() { 
     requestAnimationFrame(renderloop); 

     $this.cube.rotation.x += 0.01; 
     $this.cube.rotation.y += 0.01; 

     renderer.render(scene, camera); 
    } 

    renderloop(); 
} 

這不是很漂亮,但通常是這樣做的。如果你真的需要將renderloop作爲公共函數公開,那麼你可以 - 但我懷疑沒有理由這麼做。

+0

謝謝你隊友,這關閉了我的JS知識中的一些空白。真的很有幫助。 – CromeX

相關問題