奇怪的 JavaScript 循环发生在 Three.Js

Strange JavaScript Loop Happening with Three.Js

我正在使用 Angular 和 Three.Js 构建一个 SPA 原型来学习这两种技术。我有几个 Angular 模板可以通过导航选择,并显示不同的 3D 元素旋转。

立方体元素表现出奇怪的行为;当您导航到另一个选项卡然后导航回来时,它的旋转速度会增加。其他 3D 元素不会发生这种情况,我不明白为什么。

Here is a link to the project.

// CUBE ROTATION VALUES
var cubeRotationX = .005;
var cubeRotationY = .005;

// CUBE SIZE VALUE
var cubeSize = 1;

// LOAD A CUBE
var geometry = new THREE.BoxGeometry( cubeSize, cubeSize, cubeSize );
var material = new THREE.MeshPhongMaterial  ( { color: 0xEDEDED, } );
var cube = new THREE.Mesh( geometry, material );

// CUBE CHANGE SIZE FUNCTION
function changeCubeSize() {
    cubeSize = document.getElementById('size-selector').value;
}

// CUBE TOGGLE FUNCTION
function toggleCubeRotation() {
    if (cubeRotationX > 0) {
        cubeRotationX = 0;
        cubeRotationY = 0;
    } else {
        cubeRotationX = 0.005;
        cubeRotationY = 0.005;
    }
}

// RENDER
    function render() {
        requestAnimationFrame( render );
        cube.rotation.x += cubeRotationX;
        cube.rotation.y += cubeRotationY;
        renderer.setSize( width, height );
        renderer.render( scene, camera );
    }

显然,当离开并返回多维数据集页面时,Angular 再次运行此代码。

经过测试,我可以确认cubeRotationX和cubeRotationY是它们正确的值(0.005)。因此,循环似乎来自 cubeRotationX 和 cubeRotationY 被多次添加到 cube.rotation.x 和 cube.rotation.y,但即使我明确禁止这两行 运行 更多,循环也会发生不止一次:

if (typeof code_happened === 'undefined') {
        window.code_happened = true;
        render();
    } else {
        function reRender() {
            requestAnimationFrame( render );
            renderer.setSize( width, height );
            renderer.render( scene, camera );
        }
        reRender();
       }

说真的,我知道这很简单,但我一辈子都弄不明白。任何帮助是极大的赞赏。

根据 2pha 的建议,在这种情况下,需要做的是调用

cancelAnimationFrame( id );

对于将来使用 ThreeJs 和 Angular 模板的任何人,我只是像这样修改了我的 "only-execute-once" 函数:

if (typeof code_happened === 'undefined') {
        window.code_happened = true;
        render();
    } else {
        function reRender() {
            cancelAnimationFrame( cubeRender );
            cubeRender = requestAnimationFrame( render );
            renderer.setSize( width, height );
            renderer.render( scene, camera );
        }
        reRender();
       }

这样,当返回页面时,现有的渲染将被取消并创建一个新的渲染。在离开模板时结束渲染可能会更好,但据我所知,ThreeJs 无论如何都不会在后台渲染。