ThreeJS / Angular - «сцена не определена» - PullRequest
0 голосов
/ 16 января 2019

Я только что обнаружил ThreeJS и пытаюсь загрузить файл .obj с OBJLoader ThreeJS.

К сожалению, я получаю сообщение об ошибке

Невозможно прочитать свойство 'scene' из неопределенного

эта ошибка выдается на линии this.scene.add( object );

Вот мой полный компонент:

import { Component, OnInit } from '@angular/core';
import * as THREE from 'three';
import * as OBJLoader from 'three-obj-loader';
OBJLoader(THREE);



@Component({
  selector: 'app-items-catalog',
  templateUrl: './items-catalog.component.html',
  styleUrls: ['./items-catalog.component.css']
})
export class ItemsCatalogComponent implements OnInit {

  constructor() { 

  }

  private canEleId = 'renderCanvas';


  ngOnInit() {
    this.createScene(this.canEleId);
    this.animate();
  }

  canvas: HTMLCanvasElement;
  private renderer: THREE.WebGLRenderer;
  private camera: THREE.PerspectiveCamera;
  private scene: THREE.Scene =  new THREE.Scene();
  private light: THREE.AmbientLight;

  private cube: THREE.Mesh;


  createScene(elementId: string): void {
    //var scene = new THREE.Scene();
    // The first step is to get the reference of the canvas element from our HTML document
    this.canvas = <HTMLCanvasElement>document.getElementById(elementId);

    this.renderer = new THREE.WebGLRenderer({
      canvas: this.canvas,
      alpha: true,    // transparent background
      antialias: true // smooth edges
    });
    this.renderer.setSize(window.innerWidth, window.innerHeight);

    // create the scene


    this.camera = new THREE.PerspectiveCamera(
      75, window.innerWidth / window.innerHeight, 0.1, 1000
    );
    this.camera.position.z = 5;
    this.scene.add(this.camera);

    // soft white light
    this.light = new THREE.AmbientLight( 0x404040 );
    this.light.position.z = 10;
    this.scene.add(this.light);

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


/* HERE IS THE PART WHERE THE PROBLEM IS */ 
-----------------------------------------------------------------



    const objLoader = new THREE.OBJLoader();
    objLoader.setPath('../../assets/icon/threed/')
   // objLoader
  // var loader = new THREE.OBJLoader();

    objLoader.load(
      // resource URL
      'helicopter.obj',
      // called when resource is loaded
      function ( object ) {
        console.log(object);
        object.position.y -= 60;

       this.scene.add( object );

      },
      // called when loading is in progresses
      function ( xhr ) {

        console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

      },
      // called when loading has errors
      function ( error ) {

        console.log( 'An error happened' );

      }
    );
---------------------------------------------------------------

  }

  animate(): void {
    window.addEventListener('DOMContentLoaded', () => {
      this.render();
    });

    window.addEventListener('resize', () => {
      this.resize();
    });
  }

  render() {
    requestAnimationFrame(() => {
      this.render();
    });

    this.cube.rotation.x += 0.01;
    this.cube.rotation.y += 0.01;
    this.renderer.render(this.scene, this.camera);
  }

  resize() {
    let width = window.innerWidth;
    let height = window.innerHeight;

    this.camera.aspect = width / height;
    this.camera.updateProjectionMatrix();

    this.renderer.setSize( width, height );
  }

}

Заранее спасибо за помощь

1 Ответ

0 голосов
/ 16 января 2019

Это потому, что this в функции обратного вызова objLoader.load относится к функции onload, а не к экземпляру класса.

Один из способов решить эту проблему - создать this в переменной вcreateScene, затем используйте эту переменную вместо этой в функции загрузки:

createScene(elementId: string): void {
    let me = this;
    ...

    objLoader.load(
      // resource URL
      'helicopter.obj',
     // called when resource is loaded
     function ( object ) {
        console.log(object);
        object.position.y -= 60;

        me.scene.add( object );

     },
  ...
  );
}

Другой способ - использовать функцию стрелки, где this будет ссылаться на класс ItemsCatalogComponent:

objLoader.load(
  // resource URL
  'helicopter.obj',
  // called when resource is loaded
  ( object ) => {
    console.log(object);
    object.position.y -= 60;

   this.scene.add( object );

  },
  // called when loading is in progresses
  ( xhr ) => {

    console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

  },
  // called when loading has errors
  ( error ) => {

    console.log( 'An error happened' );

  }
);

Надеюсь, что поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...