Three.js Uncaught TypeError: невозможно прочитать свойство «рендеринг» неопределенной ошибки с литералом объекта

Я пытаюсь преобразовать свои коды в литеральный стиль объекта. Я могу создать сцену, но у меня проблемы с анимацией.

В этой строке я получаю сообщение об ошибке «Uncaught TypeError: Cannot read property 'render' of undefined».

this.renderer.render(this.scene, this.camera);

Это мой объект:

var three = {
    objects: function() {
        /*objects*/
    },
    createScene: function() {
        this.container = document.getElementById("container");

        this.scene = new THREE.Scene();

        this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.001, (26 * 10));
        this.camera.position.set(26, (26 / 2), 26);

        window.addEventListener("resize", function() {
            this.camera.aspect = window.innerWidth / window.innerHeight;
            this.camera.updateProjectionMatrix();
            this.renderer.setSize(window.innerWidth, window.innerHeight);
        });

        this.objects();

        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.container.appendChild(this.renderer.domElement);

        this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
    },
    animate: function() {
        this.renderer.render(this.scene, this.camera);
        requestAnimationFrame(this.animate);
    },
    render: function() {
        this.createScene();
        this.animate();
    }
};

three.render();

person ozgrozer    schedule 09.09.2017    source источник
comment
Значение this в прослушивателе событий не будет ссылкой на ваш объект.   -  person Pointy    schedule 09.09.2017
comment
Так нельзя ли анимировать литерал объекта?   -  person ozgrozer    schedule 09.09.2017
comment
Это так, но вы должны иметь дело с фактами того, как this получает свое значение. Вы можете объявить переменную в createScene() и присвоить ей this, а затем использовать эту ссылку в обработчике событий.   -  person Pointy    schedule 09.09.2017
comment
На самом деле это не вопрос тройки.   -  person pailhead    schedule 13.09.2017


Ответы (1)


Проверьте мой модифицированный пример (я позаимствовал вашу функцию objects для рендеринга куба... просто для удовольствия :))

По сути, вам нужно передать контекст вместе с вашим методом анимации, используя Function.prototype.bind

requestAnimationFrame(this.animate.bind(this));

... что происходит за кулисами, так это то, что первый вызов this.renderer.render(this.scene, this.camera); происходит без проблем, потому что контекст передается вместе с методом this.animate();. Однако при втором вызове animate методом requestAnimationFrame контекст отсутствует. Следовательно, вам нужно передать его вручную.

var three = {
    objects: function() {
        /*objects*/
        var geometry = new THREE.BoxBufferGeometry( 3, 3, 3 );
				var material = new THREE.MeshBasicMaterial( { color: 0xffaa00 } );
				this.mesh = new THREE.Mesh( geometry, material );
        this.mesh.position.set(24, 14, 12);
				this.scene.add( this.mesh );
    },
    createScene: function() {
        this.container = document.getElementById("container");

        this.scene = new THREE.Scene();

        this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.001, (26 * 10));
        this.camera.position.set(26, (26 / 2), 26);

        window.addEventListener("resize", function() {
            this.camera.aspect = window.innerWidth / window.innerHeight;
            this.camera.updateProjectionMatrix();
            this.renderer.setSize(window.innerWidth, window.innerHeight);
        }.bind(this));

        this.objects();

        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.container.appendChild(this.renderer.domElement);
    },
    animate: function() {
        this.mesh.rotation.x += 0.005;
				this.mesh.rotation.y += 0.01;

        this.renderer.render(this.scene, this.camera);
        requestAnimationFrame(this.animate.bind(this));
    },
    render: function() {
        this.createScene();
        this.animate();
    }
};

three.render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>

<div id="container"></div>

person Ivan Sivak    schedule 09.09.2017
comment
Ошибка Uncaught TypeError: невозможно установить свойство «аспект» неопределенной ошибки в строке this.camera.aspect = window.innerWidth / window.innerHeight; при изменении разрешения экрана. Это происходит и в ваших сниппетах. - person ozgrozer; 09.09.2017
comment
@ozgrozer Да, я думаю, потому что вы изменили размер окна ... мы должны сделать то же самое с обработчиком событий изменения размера окна. Погоди.. - person Ivan Sivak; 09.09.2017
comment
@ozgrozer Я отредактировал свой ответ. Обратите внимание на .bind(this) в конце window.addEventListener. - person Ivan Sivak; 09.09.2017