当前位置: 首页 > 知识库问答 >
问题:

三.js未捕获的范围错误:渲染循环中超出最大调用堆栈大小

邢鸿博
2023-03-14

还行。。对JS和三.js非常陌生,我很好奇为什么我在函数自调用中得到堆栈超越,以至于每个设计自然调用三.js。然而,只有当我从 main 函数中删除调用时,才会发生这种情况。

我基本上已经从三.js文档中选取了立方体示例,并且我正在尝试设置动画,以便我可以动态地从场景中添加和减少对象,并将其发送到特定的画布。

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

一旦我将渲染循环移到初始父调用之外,我就会收到一个“堆栈溢出”错误……

未捕获的 Range 错误:已超出最大调用堆栈大小

所以我的问题是,当渲染在请求AnimationFrame中调用自身时,这是可以的,但是当同样的事情发生在父调用之外时,堆栈不会被清除并且它会失败?

我错过了什么?

共有1个答案

沈茂
2023-03-14

问题出在这一行:

requestAnimationFrame( this.renderloop() );

在这里,您实际上是立即调用 renderloop(),而不是将函数作为回调传递给请求动画帧,从而导致无限递归循环

当然,有人可能会尝试将其更改为以下内容,但这也不起作用,因为传递的函数原型未绑定到任何对象:

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公开为一个公共函数,您可以这样做——但是我怀疑没有任何理由这样做。

 类似资料:
  • 我刚刚开始使用角度2。所以我尝试使用Web服务从数据库显示类别。 这是我的论坛.服务.ts文件 forum.component.ts: forum.component.html: 请帮忙,先谢了

  • 我在react中工作,基本上我想做一个带工具提示的按钮,现在我正在做工具提示。我正在更改css显示属性,以使它在鼠标进入和离开时可见或不可见。但是有一个错误,我不知道该怎么办... 这是我的代码: 在控制台中,我收到了这个错误: 我找不到问题出在哪里。我知道这可能是关于调用一个函数,而这个函数又调用另一个函数。但是我在代码中看不到这样的东西,我不确定是否都是这样。谢谢帮助:)

  • 我在玩React,我得到了我想要的功能,但是由于某个地方的无限循环,它非常慢。我相信它在组件生命周期方法中,但我不知道如何重新格式化下面的代码,使其具有相同的功能,但没有无限循环。任何关于最佳实践的建议都将不胜感激。

  • 我是React的初学者。js并试图理解道具的概念 我有两个组件 - UserData.jsx UserDataResult.jsx 在UserData中。jsx我用过这个。用户记录的状态。我想通过子组件UserDataResult.jsx显示此记录。 不知道我做错了什么,所以我在控制台日志中得到错误。 错误是:未捕获的范围错误:超出最大调用堆栈大小 代码: **UserData.jsx** **用

  • 下面的代码抛出了问题标题中提到的堆栈溢出。我正试图让一个方框阴影以脉冲效果显示在一个圆形图像的周围。有人能指出递归吗?我是一个Javascript新手,看不出来。谢谢你。 断续器 CSS 脚本

  • 我正在使用对话框,并从Material-UI和React中选择组件。 只是一个例子: 在点击select之后,我从Modal.js得到了这个错误: "未捕获的RangeError:最大调用堆栈大小超出。在HTMLDocument.Modal._this.enforceFocus(Modal.js?86a5:197)" 有什么想法吗?